Thread: Importing pg_bsd_indent into our source tree
As per the discussion at [1], here's a patchset to integrate pg_bsd_indent into our main source tree, so that people don't have to pull down a separate repo to get this tool. 0001 is a verbatim import of the current pg_bsd_indent repo contents. I felt committing this separately is useful for traceability. 0002 adjusts the copyright notices to 3-clause BSD style, so that we don't get complaints about our tree containing copyrights inconsistent with the main Postgres license. 0003 is the first non-boring bit: it updates the Makefile and some other things to account for now being an in-tree build not out-of-tree. Also, since 0002 already meant that the README isn't exactly like upstream's, I got rid of the separate README.pg_bsd_indent file and merged that info into README. 0004 is the patch discussed at [2] to improve pgindent's handling of multiline variable initializations. 0003 lacks meson support (anyone want to help with that?) but otherwise these seem committable to me. I'd anticipate pushing 0001-0003 shortly but holding 0004 until we are ready to do the post-March-CF pgindent run. (Come to think of it, 0004 had probably better include a pg_bsd_indent version bump too.) regards, tom lane [1] https://www.postgresql.org/message-id/20230123001518.6hxyiczhn4kadvmf%40awork3.anarazel.de [2] https://www.postgresql.org/message-id/flat/20230120013137.7ky7nl4e4zjorrfa%40awork3.anarazel.de commit 14985905f952032ffe4bff4f35209aeb0495e9b6 Author: Tom Lane <tgl@sss.pgh.pa.us> Date: Thu Feb 9 11:40:43 2023 -0500 Import pg_bsd_indent sources. This brings in an exact copy of the pg_bsd_indent repo as of commit d301442799cea44e5ccb04331afc537764ec77c5 (2020-12-28). diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore new file mode 100644 index 0000000000..4c5d8dc691 --- /dev/null +++ b/src/tools/pg_bsd_indent/.gitignore @@ -0,0 +1,10 @@ +# Global excludes across all subdirectories +*.o +*.obj +*.exe + +# Local excludes in root directory +/pg_bsd_indent +/*.out +/*.list +/tests.diff diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile new file mode 100644 index 0000000000..ee046f36f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/Makefile @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------- +# +# Makefile for pg_bsd_indent +# +# Copyright (c) 2017, PostgreSQL Global Development Group +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pg_bsd_indent - indent C code nicely" +PGAPPICON = win32 + +PROGRAM = pg_bsd_indent +OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) + +# clean junk left behind by "make test" +EXTRA_CLEAN = *.out *.list tests.diff + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) + +# pgxs.mk assumes too much about what "make check" means, so call it "test" +.PHONY: test + +test: $(PROGRAM) + @rm -f tests.diff + @cp $(srcdir)/tests/*.list . + @for testsrc in $(srcdir)/tests/*.0; do \ + test=`basename "$$testsrc" .0`; \ + ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ + diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ + done + @cat tests.diff + @test '!' -s tests.diff + @echo Tests complete. diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README new file mode 100644 index 0000000000..33d016db62 --- /dev/null +++ b/src/tools/pg_bsd_indent/README @@ -0,0 +1,100 @@ + + $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ + +This is the C indenter, it originally came from the University of Illinois +via some distribution tape for PDP-11 Unix. It has subsequently been +hacked upon by James Gosling @ CMU. It isn't very pretty, and really needs +to be completely redone, but it is probably the nicest C pretty printer +around. + +Further additions to provide "Kernel Normal Form" were contributed +by the folks at Sun Microsystems. + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +> From mnetor!yunexus!oz@uunet.UU.NET Wed Mar 9 15:30:55 1988 +> Date: Tue, 8 Mar 88 18:36:25 EST +> From: yunexus!oz@uunet.UU.NET (Ozan Yigit) +> To: bostic@okeeffe.berkeley.edu +> Cc: ccvaxa!willcox@uunet.UU.NET, jag@sun.com, rsalz@uunet.UU.NET +> In-Reply-To: Keith Bostic's message of Tue, 16 Feb 88 16:09:06 PST +> Subject: Re: Indent... + +Thank you for your response about indent. I was wrong in my original +observation (or mis-observation :-). UCB did keep the Illinois +copyright intact. + +The issue still is whether we can distribute indent, and if we can, which +version. David Willcox (the author) states that: + +| Several people have asked me on what basis I claim that indent is in +| the public domain. I knew I would be sorry I made that posting. +| +| Some history. Way back in 1976, the project I worked on at the +| University of Illinois Center for Advanced Computation had a huge +| battle about how to format C code. After about a week of fighting, I +| got disgusted and wrote a program, which I called indent, to reformat C +| code. It had a bunch of different options that would let you format +| the output the way you liked. In particular, all of the different +| formats being championed were supported. +| +| It was my first big C program. It was ugly. It wasn't designed, it +| just sort of grew. But it pretty much worked, and it stopped most of +| the fighting. +| +| As a matter of form, I included a University of Illinois Copyright +| notice. However, my understanding was that, since the work was done +| on an ARPA contract, it was in the public domain. +| +| Time passed. Some years later, indent showed up on one of the early +| emacs distributions. +| +| Later still, someone from UC Berkeley called the UofI and asked if +| indent was in the public domain. They wanted to include it in their +| UNIX distributions, along with the emacs stuff. I was no longer at the +| UofI, but Rob Kolstad, who was, asked me about it. I told him I didn't +| care if they used it, and since then it has been on the BSD distributions. +| +| Somewhere along the way, several other unnamed people have had their +| hands in it. It was converted to understand version 7 C. (The +| original was version 6.) It was converted from its original filter +| interface to its current "blow away the user's file" interface. +| The $HOME/.indent.pro file parsing was added. Some more formatting +| options were added. +| +| The source I have right now has two copyright notices. One is the +| original from the UofI. One is from Berkeley. +| +| I am not a lawyer, and I certainly do not understand copyright law. As +| far as I am concerned, the bulk of this program, everything covered by +| the UofI copyright, is in the public domain, and worth every penny. +| Berkeley's copyright probably should only cover their changes, and I +| don't know their feelings about sending it out. + +In any case, there appears to be none at UofI to clarify/and change +that copyright, but I am confident (based on the statements of its +author) that the code, as it stands with its copyright, is +distributable, and will not cause any legal problems. + +Hence, the issue reduces to *which* one to distribute through +comp.sources.unix. I would suggest that with the permission of you +folks (given that you have parts copyrighted), we distribute the 4.3 +version of indent, which appears to be the most up-to-date version. I +happen to have just about every known version of indent, including the +very original submission from the author to a unix tape, later the +G-Emacs version, any 4.n version, sun version and the Unipress +version. I still think we should not have to "go-back-in-time" and +re-do all the work you people have done. + +I hope to hear from you as to what you think about this. You may of +course send 4.3 version to the moderator directly, or you can let me +know of your permission, and I will send the sources, or you can let +me know that 4.3 version is off-limits, in which case we would probably +have to revert to an older version. One way or another, I hope to get +a version of indent to comp.sources.unix. + +regards.. oz + +cc: ccvaxa!willcox + sun.com!jar + uunet!rsalz + diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent new file mode 100644 index 0000000000..85c3dcac1c --- /dev/null +++ b/src/tools/pg_bsd_indent/README.pg_bsd_indent @@ -0,0 +1,30 @@ +pg_bsd_indent + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, you will need a Postgres installation, version 9.5 or newer. +(Once built, the program doesn't depend on that installation.) + +To build, just say "make"; or if pg_config from your Postgres installation +isn't in your PATH, say + make PG_CONFIG=path/to/pg_config +Optionally, run "make test" for some simple sanity checks. + +To install, copy pg_bsd_indent to somewhere in your usual PATH. +(If you say "make install", it will try to put it in your Postgres +installation directory, which is most likely not what you want for +long-term use.) + +TODO: add build support and instructions for Windows + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c new file mode 100644 index 0000000000..1c83f57049 --- /dev/null +++ b/src/tools/pg_bsd_indent/args.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include <ctype.h> +#include <err.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +#define INDENT_VERSION "2.1.1" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +static void scan_profile(FILE *); + +#define KEY_FILE 5 /* only used for args */ +#define VERSION 6 /* only used for args */ + +const char *option_source = "?"; + +void add_typedefs_from_file(const char *str); + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + const char *p_name; /* name, e.g. -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + {"T", PRO_SPECIAL, 0, KEY, 0}, + {"U", PRO_SPECIAL, 0, KEY_FILE, 0}, + {"-version", PRO_SPECIAL, 0, VERSION, 0}, + {"P", PRO_SPECIAL, 0, IGN, 0}, + {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation}, + {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop}, + {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations}, + {"bap", PRO_BOOL, false, ON, &blanklines_after_procs}, + {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments}, + {"bc", PRO_BOOL, true, OFF, &ps.leave_comma}, + {"bl", PRO_BOOL, true, OFF, &btype_2}, + {"br", PRO_BOOL, true, ON, &btype_2}, + {"bs", PRO_BOOL, false, ON, &Bill_Shannon}, + {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline}, + {"cd", PRO_INT, 0, 0, &ps.decl_com_ind}, + {"ce", PRO_BOOL, true, ON, &cuddle_else}, + {"ci", PRO_INT, 0, 0, &continuation_indent}, + {"cli", PRO_SPECIAL, 0, CLI, 0}, + {"cp", PRO_INT, 0, 0, &else_endif_com_ind}, + {"c", PRO_INT, 33, 0, &ps.com_ind}, + {"di", PRO_INT, 16, 0, &ps.decl_indent}, + {"dj", PRO_BOOL, false, ON, &ps.ljust_decl}, + {"d", PRO_INT, 0, 0, &ps.unindent_displace}, + {"eei", PRO_BOOL, false, ON, &extra_expression_indent}, + {"ei", PRO_BOOL, true, ON, &ps.else_if}, + {"fbs", PRO_BOOL, true, ON, &function_brace_split}, + {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, + {"fcb", PRO_BOOL, true, ON, &format_block_comments}, + {"ip", PRO_BOOL, true, ON, &ps.indent_parameters}, + {"i", PRO_INT, 8, 0, &ps.ind_size}, + {"lc", PRO_INT, 0, 0, &block_comment_max_col}, + {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent}, + {"lpl", PRO_BOOL, false, ON, &lineup_to_parens_always}, + {"lp", PRO_BOOL, true, ON, &lineup_to_parens}, + {"l", PRO_INT, 78, 0, &max_col}, + {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation}, + {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop}, + {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations}, + {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs}, + {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments}, + {"nbc", PRO_BOOL, true, ON, &ps.leave_comma}, + {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon}, + {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline}, + {"nce", PRO_BOOL, true, OFF, &cuddle_else}, + {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl}, + {"neei", PRO_BOOL, false, OFF, &extra_expression_indent}, + {"nei", PRO_BOOL, true, OFF, &ps.else_if}, + {"nfbs", PRO_BOOL, true, OFF, &function_brace_split}, + {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments}, + {"nfcb", PRO_BOOL, true, OFF, &format_block_comments}, + {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters}, + {"nlpl", PRO_BOOL, false, OFF, &lineup_to_parens_always}, + {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens}, + {"npcs", PRO_BOOL, false, OFF, &proc_calls_space}, + {"npro", PRO_SPECIAL, 0, IGN, 0}, + {"npsl", PRO_BOOL, true, OFF, &procnames_start_line}, + {"nsac", PRO_BOOL, false, OFF, &space_after_cast}, + {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, + {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, + {"ntpg", PRO_BOOL, false, OFF, &postgres_tab_rules}, + {"nut", PRO_BOOL, true, OFF, &use_tabs}, + {"nv", PRO_BOOL, false, OFF, &verbose}, + {"pcs", PRO_BOOL, false, ON, &proc_calls_space}, + {"psl", PRO_BOOL, true, ON, &procnames_start_line}, + {"sac", PRO_BOOL, false, ON, &space_after_cast}, + {"sc", PRO_BOOL, true, ON, &star_comment_cont}, + {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines}, + {"st", PRO_SPECIAL, 0, STDIN, 0}, + {"ta", PRO_BOOL, false, ON, &auto_typedefs}, + {"tpg", PRO_BOOL, false, ON, &postgres_tab_rules}, + {"ts", PRO_INT, 8, 0, &tabsize}, + {"ut", PRO_BOOL, true, ON, &use_tabs}, + {"v", PRO_BOOL, false, ON, &verbose}, + /* whew! */ + {0, 0, 0, 0, 0} +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +void +set_profile(const char *profile_name) +{ + FILE *f; + char fname[PATH_MAX]; + static char prof[] = ".indent.pro"; + + if (profile_name == NULL) + snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); + else + snprintf(fname, sizeof(fname), "%s", profile_name + 2); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +static void +scan_profile(FILE *f) +{ + int comment, i; + char *p; + char buf[BUFSIZ]; + + while (1) { + p = buf; + comment = 0; + while ((i = getc(f)) != EOF) { + if (i == '*' && !comment && p > buf && p[-1] == '/') { + comment = p - buf; + *p++ = i; + } else if (i == '/' && comment && p > buf && p[-1] == '*') { + p = buf + comment - 1; + comment = 0; + } else if (isspace((unsigned char)i)) { + if (p > buf && !comment) + break; + } else { + *p++ = i; + } + } + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +static const char * +eqin(const char *s1, const char *s2) +{ + while (*s1) { + if (*s1++ != *s2++) + return (NULL); + } + return (s2); +} + +/* + * Set the defaults. + */ +void +set_defaults(void) +{ + struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL) + *p->p_obj = p->p_default; +} + +void +set_option(char *arg) +{ + struct pro *p; + const char *param_start; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL) + goto found; + errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == NULL) + input = stdin; + if (output == NULL) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + add_typename(param_start); + break; + + case KEY_FILE: + if (*param_start == 0) + goto need_param; + add_typedefs_from_file(param_start); + break; + + case VERSION: + printf("pg_bsd_indent %s (based on FreeBSD indent)\n", INDENT_VERSION); + exit(0); + + default: + errx(1, "set_option: internal error: p_special %d", p->p_special); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit((unsigned char)*param_start)) { + need_param: + errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name); + } + *p->p_obj = atoi(param_start); + break; + + default: + errx(1, "set_option: internal error: p_type %d", p->p_type); + } +} + +void +add_typedefs_from_file(const char *str) +{ + FILE *file; + char line[BUFSIZ]; + + if ((file = fopen(str, "r")) == NULL) { + fprintf(stderr, "indent: cannot open file %s\n", str); + exit(1); + } + while ((fgets(line, BUFSIZ, file)) != NULL) { + /* Remove trailing whitespace */ + line[strcspn(line, " \t\n\r")] = '\0'; + add_typename(line); + } + fclose(file); +} diff --git a/src/tools/pg_bsd_indent/err.c b/src/tools/pg_bsd_indent/err.c new file mode 100644 index 0000000000..807319334b --- /dev/null +++ b/src/tools/pg_bsd_indent/err.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This is cut down to just the minimum that we need to build indent. + */ +#include "c.h" + +#include <err.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void +err(int eval, const char *fmt, ...) +{ + int code = errno; + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); + va_end(ap); + exit(eval); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(eval); +} diff --git a/src/tools/pg_bsd_indent/err.h b/src/tools/pg_bsd_indent/err.h new file mode 100644 index 0000000000..a3e8f97825 --- /dev/null +++ b/src/tools/pg_bsd_indent/err.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: stable/11/include/err.h 203964 2010-02-16 19:39:50Z imp $ + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * This is cut down to just the minimum that we need to build indent. + */ + +void err(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); +void errx(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); + +#endif /* !_ERR_H_ */ diff --git a/src/tools/pg_bsd_indent/indent.1 b/src/tools/pg_bsd_indent/indent.1 new file mode 100644 index 0000000000..131abfe70b --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.1 @@ -0,0 +1,618 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)indent.1 8.1 (Berkeley) 7/1/93 +.\" $FreeBSD: head/usr.bin/indent/indent.1 309524 2016-12-04 03:10:25Z pfg $ +.\" +.Dd December 2, 2016 +.Dt INDENT 1 +.Os +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm +.Op Ar input-file Op Ar output-file +.Op Fl bacc | Fl nbacc +.Op Fl bad | Fl nbad +.Op Fl badp | Fl nbadp +.Op Fl bap | Fl nbap +.Op Fl bbb | Fl nbbb +.Op Fl \&bc | Fl nbc +.Op Fl \&bl | Fl \&br +.Op Fl bs | Fl nbs +.Op Fl c Ns Ar n +.Op Fl cp Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Op Fl dj | Fl ndj +.Bk -words +.Op Fl ei | Fl nei +.Op Fl eei | Fl neei +.Ek +.Bk -words +.Op Fl fbs | Fl nfbs +.Op Fl fc1 | Fl nfc1 +.Op Fl fcb | Fl nfcb +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&ldi Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl \&lpl | Fl nlpl +.Op Fl npro +.Op Fl P Ns Ar file +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl sac | Fl nsac +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl \&ta +.Op Fl T Ns Ar typename +.Op Fl tpg | Fl ntpg +.Op Fl ts Ns Ar n +.Op Fl U Ns Ar file +.Op Fl ut | Fl nut +.Op Fl v | Fl \&nv +.Op Fl -version +.Sh DESCRIPTION +The +.Nm +utility is a +.Em C +program formatter. +It reformats the +.Em C +program in the +.Ar input-file +according to the switches. +The switches which can be +specified are described below. +They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input-file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input-file +and a backup copy of +.Ar input-file +is written in the current directory. +If +.Ar input-file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Sq Pa file.BAK . +.Pp +If +.Ar output-file +is specified, +.Nm +checks to make sure that it is different from +.Ar input-file . +.Pp +The options listed below control the formatting style imposed by +.Nm . +.Bl -tag -width Op +.It Fl bacc , nbacc +If +.Fl bacc +is specified, a blank line is forced around every conditional +compilation block. +For example, in front of every #ifdef and after every #endif. +Other blank lines surrounding such blocks will be swallowed. +Default: +.Fl nbacc . +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. +Default: +.Fl nbad . +.It Fl badp , nbadp +This is vaguely similar to +.Fl bad +except that it only applies to the first set of declarations +in a procedure (just after the first `{') and it causes a blank +line to be generated even if there are no declarations. +The default is +.Fl nbadp. +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. +Default: +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. +Default: +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. +Default: +.Fl \&nbc . +.It Fl \&bl , \&br +Specifying +.Fl \&bl +lines up compound statements like this: +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.It Fl bs , nbs +Whether a blank should always be inserted after sizeof. +The default is +.Fl nbs. +.It Fl c Ns Ar n +The column in which comments on code start. +The default is 33. +.It Fl cp Ns Ar n +The column in which comments on #else and #endif start. +The default is 0, which effectively separates the directives from comments by +a single space. +.It Fl cd Ns Ar n +The column in which comments on declarations start. +The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. +With +this option enabled, comments look like this: +.Bd -literal -offset indent + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. +The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing of `else's to cuddle up to the immediately preceding +`}'. +The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. +Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect +or the continuation indent is exactly half of the main indent. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0.5 +causes case labels to be indented half a tab stop. +The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. +For example, +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. +Specifying the default +.Fl \&d\&0 +lines up these comments with the code. +See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, +of global variable names and all struct/union member names +relative to the beginning of their type declaration. +The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. +The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. +If it is enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +The default is +.Fl ei . +.It Fl eei , neei +Enables (disables) extra indentation on continuation lines of +the expression part of +.Ic if +and +.Ic while +statements. +These continuation lines will be indented one extra level. +The default is +.Fl neei . +.It Fl fbs , nfbs +Enables (disables) splitting the function declaration and opening brace +across two lines. +The default is +.Fl fbs . +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. +In such cases, +.Fl nfc1 +should be +used. +The default is +.Fl fc1 . +.It Fl fcb , nfcb +Enables (disables) the formatting of block comments (ones that begin +with `/*\\n'). +Often, block comments have been not so carefully hand formatted by the +programmer, but reformatting that would just change the line breaks is not +wanted. +In such cases, +.Fl nfcb +should be used. +Block comments are then handled like box comments. +The default is +.Fl fcb . +.It Fl i Ns Ar n +The number of columns for one indentation level. +The default is 8. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. +The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. +The default is 78. +.It Fl lc Ns Ar n +Maximum length of an output line in a block comment. +The default is 0, which means to limit block comment lines in accordance with +.Fl l. +.It Fl \&ldi Ns Ar n +Specifies the indentation, in character positions, +of local variable names +relative to the beginning of their type declaration. +The default is for local variable names to be indented +by the same amount as global ones. +.It Fl \&lp , nlp +Lines up code surrounded by parentheses in continuation lines. +With +.Fl \&lp , +if a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. +For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.Bd -literal -offset indent +p1 = first_procedure(second_procedure(p2, p3), +\ \ third_procedure(p4, p5)); +.Ed +.Pp +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2,\ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5)); +.Ed +.Pp +Inserting two more newlines we get: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl \&lpl , nlpl +With +.Fl \&lpl , +code surrounded by parentheses in continuation lines is lined up even if it +would extend past the right margin. +With +.Fl \&nlpl +(the default), such a line that would extend past the right margin is moved +left to keep it within the margin, if that does not require placing it to +the left of the prevailing indentation level. +These switches have no effect if +.Fl nlp +is selected. +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl P Ns Ar file +Read profile from +.Ar file . +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. +The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. +The +default is +.Fl psl . +.It Fl sac , nsac +Control whether parenthesized type names in casts are followed by a space or +not. +The default is +.Fl nsac . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +The default is +.Fl sc . +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. +You can use this to +get rid of blank lines after declarations. +Default: +.Fl nsob . +.It Fl \&st +Causes +.Nm +to take its input from stdin and put its output to stdout. +.It Fl ta +Automatically add all identifiers ending in "_t" to the list +of type keywords. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. +Names accumulate: +.Fl T +can be specified more than once. +You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program will not be formatted as nicely as +it should. +This sounds like a painful thing to have to do, but it is really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm +cannot find all +instances of +.Ic typedef . +.It Fl tpg , ntpg +If +.Fl tpg +is specified, follow Postgres rules about when to use spaces versus +tabs for indentation, that is, use a space instead of a tab if the +tab would move only one column and no tab will follow it. +Default: +.Fl ntpg . +.It Fl ts Ns Ar n +Assumed distance between tab stops. +The default is 8. +.It Fl U Ns Ar file +Adds type names from +.Ar file +to the list of type keywords. +.It Fl ut , nut +Enables (disables) the use of tab characters in the output. +The default is +.Fl ut . +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. +When in verbose mode, +.Nm +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. +The default is +.Fl \&nv . +.It Fl -version +Causes +.Nm +to print its version number and exit. +.El +.Pp +You may set up your own `profile' of defaults to +.Nm +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. +A `.indent.pro' in the current directory takes +precedence over the one in your login directory. +If +.Nm +is run and a profile file exists, then it is read to set up the program's +defaults. +Switches on the command line, though, always override profile +switches. +The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +The +.Nm +utility +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +The +.Nm +utility fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. +Blank lines break paragraphs. +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. +Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. +If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Ss Preprocessor lines +In general, +.Nm +leaves preprocessor lines alone. +The only +reformatting that it will do is to straighten up trailing comments. +It +leaves embedded comments alone. +Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Ss C syntax +The +.Nm +utility understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. +It attempts to cope with the usual sorts of +incomplete and malformed syntax. +In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +The +.Nm +utility uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +The +.Nm +utility has even more switches than +.Xr ls 1 . +.Pp +A common mistake is to try to indent all the +.Em C +programs in a directory by typing: +.Pp +.Dl indent *.c +.Pp +This is probably a bug, not a feature. diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c new file mode 100644 index 0000000000..d3a0ecefe9 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.c @@ -0,0 +1,1279 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <sys/param.h> +#include <err.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +/* Tell indent_globs.h to define our global variables here */ +#define DECLARE_INDENT_GLOBALS 1 + +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void bakcopy(void); +static void indent_declaration(int, int); + +const char *in_name = "Standard Input"; /* will always point to name of input + * file */ +const char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +int +main(int argc, char **argv) +{ + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int force_nl; /* when true, code must be broken */ + int hd_type = 0; /* used to store type of stmt for if (...), + * for (...), etc */ + int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expression of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a <c>?<s>:<s> + * construct */ + const char *t_ptr; /* used for copying tokens */ + int tabs_to_var; /* true if using tabs to indent to var name */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + const char *profile_name = NULL; + struct parser_state transient_state; /* a copy for lookup */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + found_err = 0; + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + if (combuf == NULL) + err(1, NULL); + labbuf = (char *) malloc(bufsize); + if (labbuf == NULL) + err(1, NULL); + codebuf = (char *) malloc(bufsize); + if (codebuf == NULL) + err(1, NULL); + tokenbuf = (char *) malloc(bufsize); + if (tokenbuf == NULL) + err(1, NULL); + alloc_typenames(); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + if (in_buffer == NULL) + err(1, NULL); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + scase = ps.pcase = false; + squest = 0; + sc_end = NULL; + bp_save = NULL; + be_save = NULL; + + output = NULL; + tabs_to_var = 0; + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + lineup_to_parens_always = 0; /* -nlpl */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.local_decl_indent = -1; /* if this is not set to some nonnegative value + * by an arg, we will set this equal to + * ps.decl_ind */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_block_comments = 1; /* -fcb */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0') + profile_name = argv[i]; /* non-empty -P (set profile) */ + set_defaults(); + if (i >= argc) + set_profile(profile_name); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == NULL) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == NULL) /* check for open error */ + err(1, "%s", in_name); + continue; + } + else if (output == NULL) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + errx(1, "input and output files must be different"); + } + output = fopen(out_name, "w"); + if (output == NULL) /* check for create error */ + err(1, "%s", out_name); + continue; + } + errx(1, "unknown parameter: %s", argv[i]); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == NULL) + input = stdin; + if (output == NULL) { + if (input == stdin) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + } + + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.local_decl_indent < 0) /* if not specified by user, set this */ + ps.local_decl_indent = ps.decl_indent; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + char *p = buf_ptr; + int col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = tabsize * (1 + (col - 1) / tabsize) + 1; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int comment_buffered = false; + + type_code = lexi(&ps); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + + /* + * The following code moves newlines and comments following an if (), + * while (), else, etc. up to the start of the following stmt to + * a buffer. This allows proper handling of both kinds of brace + * placement (-br, -bl) and cuddling "else" (-ce). + */ + + while (ps.search_brace) { + switch (type_code) { + case newline: + if (sc_end == NULL) { + save_com = sc_buf; + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + *sc_end++ = '\n'; + /* + * We may have inherited a force_nl == true from the previous + * token (like a semicolon). But once we know that a newline + * has been scanned in this loop, force_nl should be false. + * + * However, the force_nl == true must be preserved if newline + * is never scanned in this loop, so this assignment cannot be + * done earlier. + */ + force_nl = false; + case form_feed: + break; + case comment: + if (sc_end == NULL) { + /* + * Copy everything from the start of the line, because + * pr_comment() will use that to calculate original + * indentation of a boxed comment. + */ + memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4); + save_com = sc_buf + (buf_ptr - in_buffer - 4); + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + comment_buffered = true; + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + if (sc_end >= &save_com[sc_size]) { /* check for temp buffer + * overflow */ + diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + case lbrace: + /* + * Put KNF-style lbraces before the buffered up tokens and + * jump out of this loop in order to avoid copying the token + * again under the default case of the switch below. + */ + if (sc_end != NULL && btype_2) { + save_com[0] = '{'; + /* + * Originally the lbrace may have been alone on its own + * line, but it will be moved into "the else's line", so + * if there was a newline resulting from the "{" before, + * it must be scanned now and ignored. + */ + while (isspace((unsigned char)*buf_ptr)) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '\n') + break; + } + goto sw_buffer; + } + /* FALLTHROUGH */ + default: /* it is the start of a normal statement */ + { + int remove_newlines; + + remove_newlines = + /* "} else" */ + (type_code == sp_nparen && *token == 'e' && + e_code != s_code && e_code[-1] == '}') + /* "else if" */ + || (type_code == sp_paren && *token == 'i' && + last_else && ps.else_if); + if (remove_newlines) + force_nl = false; + if (sc_end == NULL) { /* ignore buffering if + * comment wasn't saved up */ + ps.search_brace = false; + goto check_type; + } + while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) { + sc_end--; + } + if (swallow_optional_blanklines || + (!comment_buffered && remove_newlines)) { + force_nl = !remove_newlines; + while (sc_end > save_com && sc_end[-1] == '\n') { + sc_end--; + } + } + if (force_nl) { /* if we should insert a nl here, put + * it into the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the + * newline is read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose) /* print error msg if the line was + * not already broken */ + diag2(0, "Line broken"); + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + break; + } + } /* end of switch */ + /* + * We must make this check, just in case there was an unexpected + * EOF. + */ + if (type_code != 0) { + /* + * The only intended purpose of calling lexi() below is to + * categorize the next token in order to decide whether to + * continue buffering forthcoming tokens. Once the buffering + * is over, lexi() will be called again elsewhere on all of + * the tokens - this time for normal processing. + * + * Calling it for this purpose is a bug, because lexi() also + * changes the parser state and discards leading whitespace, + * which is needed mostly for comment-related considerations. + * + * Work around the former problem by giving lexi() a copy of + * the current parser state and discard it if the call turned + * out to be just a look ahead. + * + * Work around the latter problem by copying all whitespace + * characters into the buffer so that the later lexi() call + * will read them. + */ + if (sc_end != NULL) { + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + *sc_end++ = *buf_ptr++; + if (sc_end >= &save_com[sc_size]) { + errx(1, "input too long"); + } + } + if (buf_ptr >= buf_end) { + fill_buffer(); + } + } + transient_state = ps; + type_code = lexi(&transient_state); /* read another token */ + if (type_code != newline && type_code != form_feed && + type_code != comment && !transient_state.search_brace) { + ps = transient_state; + } + } + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag2(1, "Stuff missing from end of file"); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + int len = e_com - s_com; + + CHECK_SIZE_CODE(len + 3); + *e_code++ = ' '; + memcpy(e_code, s_com, len); + e_code += len; + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE(3); /* maximum number of increments of e_code + * before the next CHECK_SIZE_CODE or + * dump_line() is 2. After that there's the + * final increment for the null character. */ + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + /* count parens to make Healy happy */ + if (++ps.p_l_follow == nitems(ps.paren_indents)) { + diag3(0, "Reached internal limit of %d unclosed parens", + nitems(ps.paren_indents)); + ps.p_l_follow--; + } + if (*token == '[') + /* not a function pointer declaration or a function call */; + else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* function pointer declarations */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank && + ((ps.last_token != ident && ps.last_token != funcname) || + /* offsetof (1) is never allowed a space; sizeof (2) gets + * one iff -bs; all other keywords (>2) always get a space + * before lparen */ + ps.keyword + Bill_Shannon > 2)) + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + /* + * parenthesized type following sizeof or offsetof is not a cast, + * and we assume the same for any other non-keyword identifier, + * to support macros that take types + */ + if (ps.last_token == ident && + (ps.keyword == 0 || ps.keyword == 1 || ps.keyword == 2)) + ps.not_cast_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + ps.want_blank = space_after_cast; + } else + ps.want_blank = true; + ps.not_cast_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag3(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* pointer declarations */ + + /* + * if this is a unary op in a declaration, we should indent + * this token + */ + for (i = 0; token[i]; ++i) + /* find length of token */; + indent_declaration(dec_ind - i, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank) + *e_code++ = ' '; + + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len); + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * <c>?<n>:<n> construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_or_st) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + /* + * turn everything so far into a label + */ + { + int len = e_code - s_code; + + CHECK_SIZE_LAB(len + 3); + memcpy(e_lab, s_code, len); + e_lab += len; + *e_lab++ = ':'; + *e_lab = '\0'; + e_code = s_code; + } + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + if (ps.dec_nest == 0) + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in an error */ + squest = 0; + if (ps.last_token == rparen) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.not_cast_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent stray semicolons in declarations */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for an if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after an end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + if (function_brace_split) { /* dump the line prior to the + * brace ... */ + dump_line(); + ps.want_blank = false; + } else /* add a space between the decl and brace */ + ps.want_blank = true; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceding unbalanced + * parens */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest] = dec_ind; + if (++ps.dec_nest == nitems(di_stack)) { + diag3(0, "Reached internal limit of %d struct levels", + nitems(di_stack)); + ps.dec_nest--; + } + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we can't be in the middle of + * a declaration, so don't do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + ps.in_decl = false; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag2(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case type_def: + case storage: + prefix_blankline_requested = 0; + goto copy_id; + + case structure: + if (ps.p_l_follow > 0) + goto copy_id; + /* FALLTHROUGH */ + case decl: /* we have a declaration type (int, etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + if (ps.ind_level == 0 || ps.dec_nest > 0) { + /* global variable or struct member in local variable */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); + } else { + /* local variable */ + dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; + tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); + } + goto copy_id; + + case funcname: + case ident: /* got an identifier or constant */ + if (ps.in_decl) { + if (type_code == funcname) { + ps.in_decl = false; + if (procnames_start_line && s_code != e_code) { + *e_code = '\0'; + dump_line(); + } + else if (ps.want_blank) { + *e_code++ = ' '; + } + ps.want_blank = false; + } + else if (!ps.block_init && !ps.dumped_decl_indent && + ps.paren_level == 0) { /* if we are in a declaration, we + * must indent identifier */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + ps.want_blank = false; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, s_token, len); + e_code += len; + } + if (type_code != funcname) + ps.want_blank = true; + break; + + case strpfx: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent leading commas and not the actual identifiers */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || + count_spaces_until(compute_code_target(), s_code, e_code) > + max_col - tabsize)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + CHECK_SIZE_LAB(1); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || (in_comment && !had_eof)) { + CHECK_SIZE_LAB(2); + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == NULL) { + /* comment on preprocessor line */ + if (sc_end == NULL) { /* if this is the first comment, + * we must set up the buffer */ + save_com = sc_buf; + sc_end = &save_com[0]; + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + if (sc_end - save_com + com_end - com_start > sc_size) + errx(1, "input too long"); + memmove(sc_end, s_lab + com_start, com_end - com_start); + sc_end += com_end - com_start; + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + } + CHECK_SIZE_LAB(1); + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */ + if ((size_t)ifdef_level < nitems(state_stack)) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag2(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */ + if (ifdef_level <= 0) + diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag2(1, "Unmatched #endif"); + else + ifdef_level--; + } else { + struct directives { + int size; + const char *string; + } + recognized[] = { + {7, "include"}, + {6, "define"}, + {5, "undef"}, + {4, "line"}, + {5, "error"}, + {6, "pragma"} + }; + int d = nitems(recognized); + while (--d >= 0) + if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0) + break; + if (d < 0) { + diag2(1, "Unrecognized cpp directive"); + break; + } + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + else { + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a / followed by * this is a biggie */ + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +static void +bakcopy(void) +{ + int n, + bakchn; + char buff[8 * 1024]; + const char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(1, "%s", bakfile); + while ((n = read(fileno(input), buff, sizeof(buff))) > 0) + if (write(bakchn, buff, n) != n) + err(1, "%s", bakfile); + if (n < 0) + err(1, "%s", in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == NULL) + err(1, "%s", bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == NULL) { + unlink(bakfile); + err(1, "%s", in_name); + } +} + +static void +indent_declaration(int cur_dec_ind, int tabs_to_var) +{ + int pos = e_code - s_code; + char *startpos = e_code; + + /* + * get the tab math right for indentations that are not multiples of tabsize + */ + if ((ps.ind_level * ps.ind_size) % tabsize != 0) { + pos += (ps.ind_level * ps.ind_size) % tabsize; + cur_dec_ind += (ps.ind_level * ps.ind_size) % tabsize; + } + if (tabs_to_var) { + int tpos; + + CHECK_SIZE_CODE(cur_dec_ind / tabsize); + while ((tpos = tabsize * (1 + pos / tabsize)) <= cur_dec_ind) { + *e_code++ = (!postgres_tab_rules || + tpos != pos + 1 || + cur_dec_ind >= tpos + tabsize) ? '\t' : ' '; + pos = tpos; + } + } + CHECK_SIZE_CODE(cur_dec_ind - pos + 1); + while (pos < cur_dec_ind) { + *e_code++ = ' '; + pos++; + } + if (e_code == startpos && ps.want_blank) { + *e_code++ = ' '; + ps.want_blank = false; + } +} diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h new file mode 100644 index 0000000000..1708dbc19f --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2001 Jens Schweikhardt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); +#endif + +#define nitems(array) (sizeof (array) / sizeof (array[0])) + +void add_typename(const char *); +void alloc_typenames(void); +int compute_code_target(void); +int compute_label_target(void); +int count_spaces(int, char *); +int count_spaces_until(int, char *, char *); +int lexi(struct parser_state *); +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); +void set_defaults(void); +void set_option(char *); +void set_profile(const char *); diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h new file mode 100644 index 0000000000..24c43fa420 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_codes.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_codes.h 309380 2016-12-02 01:25:51Z pfg $ + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 +#define strpfx 33 +#define storage 34 +#define funcname 35 +#define type_def 36 +#define structure 37 diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h new file mode 100644 index 0000000000..398784b3f4 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -0,0 +1,343 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_globs.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_globs.h 303735 2016-08-03 22:08:07Z pfg $ + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + + +#ifndef false +#define false 0 +#endif +#ifndef true +#define true 1 +#endif + +/* + * Exactly one calling file should define this symbol. The global variables + * will be defined in that file, and just referenced elsewhere. + */ +#ifdef DECLARE_INDENT_GLOBALS +#define extern +#endif + +extern FILE *input; /* the fid for the input file */ +extern FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE(desired_size) \ + if (e_code + (desired_size) >= l_code) { \ + int nsize = l_code-s_code + 400 + desired_size; \ + int code_len = e_code-s_code; \ + codebuf = (char *) realloc(codebuf, nsize); \ + if (codebuf == NULL) \ + err(1, NULL); \ + e_code = codebuf + code_len + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM(desired_size) \ + if (e_com + (desired_size) >= l_com) { \ + int nsize = l_com-s_com + 400 + desired_size; \ + int com_len = e_com - s_com; \ + int blank_pos; \ + if (last_bl != NULL) \ + blank_pos = last_bl - combuf; \ + else \ + blank_pos = -1; \ + combuf = (char *) realloc(combuf, nsize); \ + if (combuf == NULL) \ + err(1, NULL); \ + e_com = combuf + com_len + 1; \ + if (blank_pos > 0) \ + last_bl = combuf + blank_pos; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB(desired_size) \ + if (e_lab + (desired_size) >= l_lab) { \ + int nsize = l_lab-s_lab + 400 + desired_size; \ + int label_len = e_lab - s_lab; \ + labbuf = (char *) realloc(labbuf, nsize); \ + if (labbuf == NULL) \ + err(1, NULL); \ + e_lab = labbuf + label_len + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN(desired_size) \ + if (e_token + (desired_size) >= l_token) { \ + int nsize = l_token-s_token + 400 + desired_size; \ + int token_len = e_token - s_token; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + if (tokenbuf == NULL) \ + err(1, NULL); \ + e_token = tokenbuf + token_len + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +extern char *labbuf; /* buffer for label */ +extern char *s_lab; /* start ... */ +extern char *e_lab; /* .. and end of stored label */ +extern char *l_lab; /* limit of label buffer */ + +extern char *codebuf; /* buffer for code section */ +extern char *s_code; /* start ... */ +extern char *e_code; /* .. and end of stored code */ +extern char *l_code; /* limit of code section */ + +extern char *combuf; /* buffer for comments */ +extern char *s_com; /* start ... */ +extern char *e_com; /* ... and end of stored comments */ +extern char *l_com; /* limit of comment buffer */ + +#define token s_token +extern char *tokenbuf; /* the last token scanned */ +extern char *s_token; +extern char *e_token; +extern char *l_token; + +extern char *in_buffer; /* input buffer */ +extern char *in_buffer_limit; /* the end of the input buffer */ +extern char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +extern char *buf_end; /* ptr to first after last char in in_buffer */ + +extern char sc_buf[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +extern char *save_com; /* start of the comment stored in sc_buf */ +extern char *sc_end; /* pointer into save_com buffer */ + +extern char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +extern char *be_save; /* similarly saved value of buf_end */ + + +extern int found_err; +extern int blanklines_after_declarations; +extern int blanklines_before_blockcomments; +extern int blanklines_after_procs; +extern int blanklines_around_conditional_compilation; +extern int swallow_optional_blanklines; +extern int n_real_blanklines; +extern int prefix_blankline_requested; +extern int postfix_blankline_requested; +extern int break_comma; /* when true and not in parens, break after a + * comma */ +extern int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +extern float case_ind; /* indentation level to be used for a "case + * n:" */ +extern int code_lines; /* count of lines with code */ +extern int had_eof; /* set to true when input is exhausted */ +extern int line_no; /* the current line number. */ +extern int max_col; /* the maximum allowable line length */ +extern int verbose; /* when true, non-essential error messages are + * printed */ +extern int cuddle_else; /* true if else should cuddle up to '}' */ +extern int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +extern int comment_delimiter_on_blankline; +extern int troff; /* true iff were generating troff input */ +extern int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +extern int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +extern int format_block_comments; /* true if comments beginning with + * `/ * \n' are to be reformatted */ +extern int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +extern int inhibit_formatting; /* true if INDENT OFF is in effect */ +extern int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +extern int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +extern int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +extern int lineup_to_parens_always; /* if true, do not attempt to keep + * lined-up code within the margin */ +extern int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +extern int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +extern int block_comment_max_col; +extern int extra_expression_indent; /* true if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ +extern int function_brace_split; /* split function declaration and + * brace onto separate lines */ +extern int use_tabs; /* set true to use tabs for spacing, + * false uses all spaces */ +extern int auto_typedefs; /* set true to recognize identifiers + * ending in "_t" like typedefs */ +extern int space_after_cast; /* "b = (int) a" vs "b = (int)a" */ +extern int postgres_tab_rules; /* use Postgres tab-vs-space rules */ +extern int tabsize; /* the size of a tab */ +extern int else_endif_com_ind; /* the column in which comments to + * the right of #else and #endif + * should start */ + +extern int ifdef_level; + +struct parser_state { + int last_token; + int p_stack[256]; /* this is the parsers stack */ + int il[64]; /* this stack stores indentation levels */ + float cstk[32]; /* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in / followed by * */ + int comment_delta; /* used to set up indentation for all lines + * of a boxed comment after the first one */ + int n_comment_delta;/* remembers how many columns there were + * before the start of a box comment so that + * forthcoming lines of the comment are + * indented properly */ + int cast_mask; /* indicates which close parens potentially + * close off casts */ + int not_cast_mask; /* indicates which close parens definitely + * close off something else than casts */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * comment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within statements */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int local_decl_indent; /* like decl_indent but for locals */ + int keyword; /* the type of a keyword or 0 */ + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +}; + +extern struct parser_state ps; +extern struct parser_state state_stack[5]; +extern struct parser_state match_state[5]; + +/* Undo previous hackery */ +#ifdef DECLARE_INDENT_GLOBALS +#undef extern +#endif diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c new file mode 100644 index 0000000000..3ce8bfb70c --- /dev/null +++ b/src/tools/pg_bsd_indent/io.c @@ -0,0 +1,608 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +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 +dump_line(void) +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + int cur_col, + target_col = 1; + static int not_first_line; + + if (ps.procname[0]) { + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) { + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + *e_lab = '\0'; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + (int)(e_lab - s), s); + } + else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + int i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) { /* print comment, if any */ + int target = ps.com_col; + char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') /* consider original indentation in + * case this is a box comment */ + com_st++, target += tabsize; + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = tabsize * (1 + (target - 1) / tabsize) + 1, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment can't fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace((unsigned char)e_com[-1])) + e_com--; + (void)pad_output(cur_col, target); + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com = combuf + 1) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + if (ps.paren_level > 0) + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; +} + +int +compute_code_target(void) +{ + int target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent + * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level); + else if (lineup_to_parens_always) + target_col = paren_target; + else { + int w; + int t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int +compute_label_target(void) +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : 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 + * + * All rights reserved + * + * + * NAME: fill_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 + * buffer from temporary buffer + * + */ +void +fill_buffer(void) +{ /* this routine reads stuff from the input */ + char *p; + int i; + FILE *f = input; + + if (bp_save != NULL) { /* there is a partly filled input buffer left */ + 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 */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + int size = (in_buffer_limit - in_buffer) * 2 + 10; + int offset = p - in_buffer; + in_buffer = realloc(in_buffer, size); + if (in_buffer == NULL) + errx(1, "input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + 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; + } + buf_ptr = in_buffer; + buf_end = p; + if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') { + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + } + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column + * target integer The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +static int +pad_output(int current, int target) + /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + /* current: the current column value */ + /* target: position we want it at */ +{ + int curr; /* internal column pointer */ + + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + if (use_tabs) { + int tcur; + + while ((tcur = tabsize * (1 + (curr - 1) / tabsize) + 1) <= target) { + putc((!postgres_tab_rules || + tcur != curr + 1 || + target >= tcur + tabsize) ? '\t' : ' ', output); + curr = tcur; + } + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces_until(int cur, char *buffer, char *end) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ +{ + char *buf; /* used to look thru buffer */ + + for (buf = buffer; *buf != '\0' && buf != end; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = tabsize * (1 + (cur - 1) / tabsize) + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +int +count_spaces(int cur, char *buffer) +{ + return (count_spaces_until(cur, buffer, NULL)); +} + +void +diag4(int level, const char *msg, int a, int b) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void +diag3(int level, const char *msg, int a) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a); + fprintf(stderr, "\n"); + } +} + +void +diag2(int level, const char *msg) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, "%s", msg); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, "%s", msg); + fprintf(stderr, "\n"); + } +} + diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c new file mode 100644 index 0000000000..f01596a870 --- /dev/null +++ b/src/tools/pg_bsd_indent/lexi.c @@ -0,0 +1,724 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include <err.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +#define alphanum 1 +#ifdef undef +#define opchar 3 +#endif + +struct templ { + const char *rwd; + int rwcode; +}; + +/* + * This table has to be sorted alphabetically, because it'll be used in binary + * search. For the same reason, string must be the first thing in struct templ. + */ +struct templ specials[] = +{ + {"_Bool", 4}, + {"_Complex", 4}, + {"_Imaginary", 4}, + {"auto", 10}, + {"bool", 4}, + {"break", 9}, + {"case", 8}, + {"char", 4}, + {"complex", 4}, + {"const", 4}, + {"continue", 12}, + {"default", 8}, + {"do", 6}, + {"double", 4}, + {"else", 6}, + {"enum", 3}, + {"extern", 10}, + {"float", 4}, + {"for", 5}, + {"global", 4}, + {"goto", 9}, + {"if", 5}, + {"imaginary", 4}, + {"inline", 12}, + {"int", 4}, + {"long", 4}, + {"offsetof", 1}, + {"register", 10}, + {"restrict", 12}, + {"return", 9}, + {"short", 4}, + {"signed", 4}, + {"sizeof", 2}, + {"static", 10}, + {"struct", 3}, + {"switch", 7}, + {"typedef", 11}, + {"union", 3}, + {"unsigned", 4}, + {"void", 4}, + {"volatile", 4}, + {"while", 5} +}; + +const char **typenames; +int typename_count; +int typename_top = -1; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + +static int +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) +{ + int unary_delim; /* this is set to 1 if the current token + * forces a following operator to be unary */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + state->col_1 = state->last_nl; /* tell world that this token started + * in column 1 iff the last thing + * scanned was a newline */ + state->last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + state->col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr & 127] == alphanum || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + /* + * we have a character or number + */ + struct templ *p; + + if (isdigit((unsigned char)*buf_ptr) || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + int seendot = 0, + seenexp = 0, + seensfx = 0; + + /* + * base 2, base 8, base 16: + */ + if (buf_ptr[0] == '0' && buf_ptr[1] != '.') { + int len; + + if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B') + len = strspn(buf_ptr + 2, "01") + 2; + else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X') + len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2; + else + len = strspn(buf_ptr + 1, "012345678") + 1; + if (len > 0) { + CHECK_SIZE_TOKEN(len); + memcpy(e_token, buf_ptr, len); + e_token += len; + buf_ptr += len; + } + else + diag2(1, "Unterminated literal"); + } + else /* base 10: */ + while (1) { + if (*buf_ptr == '.') { + if (seendot) + break; + else + seendot++; + } + CHECK_SIZE_TOKEN(3); + *e_token++ = *buf_ptr++; + if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') { + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + } + + while (1) { + CHECK_SIZE_TOKEN(2); + if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) { + *e_token++ = *buf_ptr++; + seensfx |= 1; + continue; + } + if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) { + if (buf_ptr[1] == buf_ptr[0]) + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + seensfx |= 2; + continue; + } + break; + } + } + else + while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) { + /* fill_buffer() terminates buffer with newline */ + if (*buf_ptr == BACKSLASH) { + if (*(buf_ptr + 1) == '\n') { + buf_ptr += 2; + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; + } + CHECK_SIZE_TOKEN(1); + /* copy it over */ + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token = '\0'; + + if (s_token[0] == 'L' && s_token[1] == '\0' && + (*buf_ptr == '"' || *buf_ptr == '\'')) + return (strpfx); + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + state->keyword = 0; + if (state->last_token == structure && !state->p_l_follow) { + /* if last token was 'struct' and we're not + * in parentheses, then this token + * should be treated as a declaration */ + state->last_u_d = true; + return (decl); + } + /* + * Operator after identifier is binary unless last token was 'struct' + */ + state->last_u_d = (state->last_token == structure); + + p = bsearch(s_token, + specials, + sizeof(specials) / sizeof(specials[0]), + sizeof(specials[0]), + strcmp_type); + if (p == NULL) { /* not a special keyword... */ + char *u; + + /* ... so maybe a type_t or a typedef */ + if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) && + strcmp(u, "_t") == 0) || (typename_top >= 0 && + bsearch(s_token, typenames, typename_top + 1, + sizeof(typenames[0]), strcmp_type))) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + goto found_typename; + } + } else { /* we have a keyword */ + state->keyword = p->rwcode; + state->last_u_d = true; + switch (p->rwcode) { + case 7: /* it is a switch */ + return (swstmt); + case 8: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + /* FALLTHROUGH */ + case 4: /* one of the declaration keywords */ + found_typename: + if (state->p_l_follow) { + /* inside parens: cast, param list, offsetof or sizeof */ + state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask; + } + if (state->last_token == period || state->last_token == unary_op) { + state->keyword = 0; + break; + } + if (p != NULL && p->rwcode == 3) + return (structure); + if (state->p_l_follow) + break; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 10: /* storage class specifier */ + return (storage); + + case 11: /* typedef */ + return (type_def); + + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 && + state->in_parameter_declaration == 0 && state->block_init == 0) { + 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 + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + else if (!state->p_l_follow && !state->block_init && + !state->in_stmt && + ((*buf_ptr == '*' && buf_ptr[1] != '=') || + isalpha((unsigned char)*buf_ptr)) && + (state->last_token == semicolon || state->last_token == lbrace || + state->last_token == rbrace)) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + return decl; + } + if (state->last_token == decl) /* if this is a declared variable, + * then following sign is unary */ + state->last_u_d = true; /* will make "int a -1" work */ + return (ident); /* the ident is not in the list */ + } /* end of processing for alphanum character */ + + /* Scan a non-alphanumeric token */ + + CHECK_SIZE_TOKEN(3); /* things like "<<=" */ + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = state->last_u_d; + state->last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exhausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + do { /* copy the string */ + while (1) { /* move one character or [/<char>]<char> */ + if (*buf_ptr == '\n') { + diag2(1, "Unterminated literal"); + goto stop_lit; + } + CHECK_SIZE_TOKEN(2); + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = state->last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (state->in_or_st) state->block_init = 1; + */ + /* ? code = state->block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = state->block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = state->last_u_d; + state->last_nl = true; /* remember this so we can set 'state->col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (state->last_token == ident || state->last_token == rparen) { + code = (state->last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + unary_delim = false; + code = unary_op; + state->want_blank = false; + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (state->in_or_st) + state->block_init = 1; +#ifdef undef + if (chartype[*buf_ptr & 127] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + case '*': + unary_delim = true; + if (!state->last_u_d) { + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = binary_op; + break; + } + while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) { + if (*buf_ptr == '*') { + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + } + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = unary_op; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = state->last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + state->last_u_d = unary_delim; + CHECK_SIZE_TOKEN(1); + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +void +alloc_typenames(void) +{ + + typenames = (const char **)malloc(sizeof(typenames[0]) * + (typename_count = 16)); + if (typenames == NULL) + err(1, NULL); +} + +void +add_typename(const char *key) +{ + int comparison; + const char *copy; + + if (typename_top + 1 >= typename_count) { + typenames = realloc((void *)typenames, + sizeof(typenames[0]) * (typename_count *= 2)); + if (typenames == NULL) + err(1, NULL); + } + if (typename_top == -1) + typenames[++typename_top] = copy = strdup(key); + else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) { + /* take advantage of sorted input */ + if (comparison == 0) /* remove duplicates */ + return; + typenames[++typename_top] = copy = strdup(key); + } + else { + int p; + + for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++) + /* find place for the new key */; + if (comparison == 0) /* remove duplicates */ + return; + memmove(&typenames[p + 1], &typenames[p], + sizeof(typenames[0]) * (++typename_top - p)); + typenames[p] = copy = strdup(key); + } + + if (copy == NULL) + err(1, NULL); +} diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c new file mode 100644 index 0000000000..bf6b1697f9 --- /dev/null +++ b/src/tools/pg_bsd_indent/parse.c @@ -0,0 +1,342 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void reduce(void); + +void +parse(int tk) /* tk: the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + /* + * Note that the stack pointer here is decremented, effectively + * reducing "else if" to "if". This saves a lot of stack space + * in case of a long "if-else-if ... else-if" sequence. + */ + ps.i_l_follow = ps.il[ps.tos--]; + /* the rest is the same as for dolit and forstmt */ + /* FALLTHROUGH */ + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag2(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ + if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag2(1, "Statement nesting error"); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag2(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + if (ps.tos >= nitems(ps.p_stack) - 1) + errx(1, "Parser stack overflow"); + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * <stmt> <stmt> <stmtl> + * <stmtl> <stmt> <stmtl> + * do <stmt> "dostmt" + * if <stmt> "ifstmt" + * switch <stmt> <stmt> + * decl <stmt> <stmt> + * "ifelse" <stmt> <stmt> + * for <stmt> <stmt> + * while <stmt> <stmt> + * "dostmt" while <stmt> + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +static void +reduce(void) +{ + int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* <do> <stmt> */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* <if> <stmt> */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* <switch> <stmt> */ + case_ind = ps.cstk[ps.tos - 1]; + /* FALLTHROUGH */ + case decl: /* finish of a declaration */ + case elsehead: + /* <<if> <stmt> else> <stmt> */ + case forstmt: + /* <for> <stmt> */ + case whilestmt: + /* <while> <stmt> */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* <anything else> <stmt> */ + return; + + } /* end of section for <stmt> on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.tos -= 2; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c new file mode 100644 index 0000000000..b0eacac1bb --- /dev/null +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + +void +pr_comment(void) +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = NULL; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + break_delim = false; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*' || + (*buf_ptr == '\n' && !format_block_comments)) { + ps.box_com = true; /* A comment with a '-' or '*' immediately + * after the /+* is assumed to be a boxed + * comment. A comment with a newline + * immediately after the /+* is assumed to + * be a block comment and is treated as a + * box comment unless format_block_comments + * is nonzero (the default). */ + break_delim = false; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + int target_col; + break_delim = false; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + if (s_lab != e_lab && s_lab[1] == 'e' && + (strncmp(s_lab, "#endif", 6) == 0 || + strncmp(s_lab, "#else", 5) == 0)) + ps.com_col = else_endif_com_ind <= target_col + ? target_col + 1 : else_endif_com_ind; + else + ps.com_col = ps.decl_on_line || ps.ind_level == 0 + ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col <= target_col) + ps.com_col = tabsize * (1 + (target_col - 1) / tabsize) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + /* + * Find out how much indentation there was originally, because that + * much will have to be ignored by pad_output() in dump_line(). This + * is a box comment, so nothing changes -- not even indentation. + * + * The comment we're about to read usually comes from in_buffer, + * unless it has been copied into save_com. + */ + char *start; + + start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? + sc_buf : in_buffer; + ps.n_comment_delta = 1 - count_spaces_until(1, start, buf_ptr - 2); + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/' followed by '*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + /* + * Don't put a break delimiter if this is a one-liner that won't wrap. + */ + if (break_delim) + for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) { + if (t_ptr >= buf_end) + fill_buffer(); + if (t_ptr[0] == '*' && t_ptr[1] == '/') { + if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2)) + break_delim = false; + break; + } + } + + if (break_delim) { + char *t = e_com; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments && ps.last_token != lbrace) + prefix_blankline_requested = 1; + dump_line(); + e_com = s_com = t; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + CHECK_SIZE_COM(3); + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = NULL; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t') + ; + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + dump_line(); + return; + } + last_bl = NULL; + CHECK_SIZE_COM(4); + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) + *e_com++ = ' '; + if (!ps.box_com && e_com - s_com > 3) { + dump_line(); + if (star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + else { + ps.last_nl = 1; + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + *e_com++ = ' '; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + CHECK_SIZE_COM(4); + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + if (break_delim) { + if (e_com > s_com + 3) { + dump_line(); + } + else + s_com = e_com; + *e_com++ = ' '; + } + if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com) + *e_com++ = ' '; /* ensure blank before end */ + *e_com++ = '*', *e_com++ = '/', *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else /* handle isolated '*' */ + *e_com++ = '*'; + break; + default: /* we have a random char */ + now_col = count_spaces_until(ps.com_col, s_com, e_com); + do { + CHECK_SIZE_COM(1); + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; /* remember we saw a blank */ + ++e_com; + now_col++; + } while (!memchr("*\n\r\b\t", *buf_ptr, 6) && + (now_col <= adj_max_col || !last_bl)); + ps.last_nl = false; + if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (last_bl == NULL) { + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + break; + } + *e_com = '\0'; + e_com = last_bl; + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t'; + t_ptr++) + ; + last_bl = NULL; + /* + * t_ptr will be somewhere between e_com (dump_line() reset) + * and l_com. So it's safe to copy byte by byte from t_ptr + * to e_com without any CHECK_SIZE_COM(). + */ + while (*t_ptr != '\0') { + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + break; + } + } +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0 b/src/tools/pg_bsd_indent/tests/binary.0 new file mode 100644 index 0000000000..0c5ebf7e8f --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0 @@ -0,0 +1,9 @@ +#define b00101010 -1 +void t(void) { + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0.stdout b/src/tools/pg_bsd_indent/tests/binary.0.stdout new file mode 100644 index 0000000000..6118ac5055 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0.stdout @@ -0,0 +1,11 @@ +#define b00101010 -1 +void +t(void) +{ + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0 b/src/tools/pg_bsd_indent/tests/comments.0 new file mode 100644 index 0000000000..7b65c2eb55 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0 @@ -0,0 +1,52 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void t(void) { + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on the next line. + * + * *test* + */ + + /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */ + + /* r309343 */ +} + +int c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0.stdout b/src/tools/pg_bsd_indent/tests/comments.0.stdout new file mode 100644 index 0000000000..8ca5aa518c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0.stdout @@ -0,0 +1,60 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void +t(void) +{ + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj + * kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on + * the next line. + * + * *test* + */ + + /* + * r309219 Go through linked list, freeing from the malloced (t[-1]) + * address. + */ + + /* r309343 */ +} + +int +c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.pro b/src/tools/pg_bsd_indent/tests/comments.pro new file mode 100644 index 0000000000..0959711b3d --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.pro @@ -0,0 +1 @@ +-bbb \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0 b/src/tools/pg_bsd_indent/tests/cppelsecom.0 new file mode 100644 index 0000000000..79aed65115 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0 @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout new file mode 100644 index 0000000000..047fc3d951 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/declarations.0 b/src/tools/pg_bsd_indent/tests/declarations.0 new file mode 100644 index 0000000000..8419494989 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0 @@ -0,0 +1,79 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct +{ + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex +{ + double x; + double y; +} Complex; + +void +t1 (char *a, int b, + void (*fn)(void)) +{} + +void t2 (char *x, int y) +{ + int a, + b, + c; + int + *d, + *e, + *f; + int (*g)(), + (*h)(), + (*i)(); + int j, + k, + l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int *int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( +struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/declarations.0.stdout b/src/tools/pg_bsd_indent/tests/declarations.0.stdout new file mode 100644 index 0000000000..ab5a447a8b --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0.stdout @@ -0,0 +1,73 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct { + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex { + double x; + double y; +} Complex; + +void +t1(char *a, int b, + void (*fn) (void)) +{ +} + +void +t2(char *x, int y) +{ + int a, b, c; + int + *d, *e, *f; + int (*g) (), (*h) (), (*i) (); + int j, k, l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], + x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int * +int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( + struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0 b/src/tools/pg_bsd_indent/tests/elsecomment.0 new file mode 100644 index 0000000000..61066c22b5 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0 @@ -0,0 +1,42 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void t(void) { + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ int a; else /* b */ int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) { + int a; + } + + + else if (0) { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout new file mode 100644 index 0000000000..7de23be089 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout @@ -0,0 +1,47 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void +t(void) +{ + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) + { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) + { + int a; + } else if (0) + { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.pro b/src/tools/pg_bsd_indent/tests/elsecomment.pro new file mode 100644 index 0000000000..115c4768e7 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.pro @@ -0,0 +1 @@ +-bl \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/enum.0 b/src/tools/pg_bsd_indent/tests/enum.0 new file mode 100644 index 0000000000..15057dc464 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0 @@ -0,0 +1,6 @@ +typedef enum +{ +PREWARM_PREFETCH, /* comment */ +PREWARM_READ, /* more comment */ +PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/enum.0.stdout b/src/tools/pg_bsd_indent/tests/enum.0.stdout new file mode 100644 index 0000000000..fd4653b854 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0.stdout @@ -0,0 +1,5 @@ +typedef enum { + PREWARM_PREFETCH, /* comment */ + PREWARM_READ, /* more comment */ + PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0 b/src/tools/pg_bsd_indent/tests/f_decls.0 new file mode 100644 index 0000000000..aeef03b704 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0 @@ -0,0 +1,27 @@ +char * x(void) +{ + type identifier; + type *pointer; + unused * value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) { + +} + +int +z(void) { + +} + +int x; +int *y; +int * * * * z; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0.stdout b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout new file mode 100644 index 0000000000..bc21248552 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout @@ -0,0 +1,30 @@ +char * +x(void) +{ + type identifier; + type *pointer; + unused *value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) +{ + +} + +int +z(void) +{ + +} + +int x; +int *y; +int ****z; diff --git a/src/tools/pg_bsd_indent/tests/float.0 b/src/tools/pg_bsd_indent/tests/float.0 new file mode 100644 index 0000000000..91f017fc1c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void t(void) { + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/float.0.stdout b/src/tools/pg_bsd_indent/tests/float.0.stdout new file mode 100644 index 0000000000..0f213182ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0.stdout @@ -0,0 +1,8 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void +t(void) +{ + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0 b/src/tools/pg_bsd_indent/tests/label.0 new file mode 100644 index 0000000000..7798a4d5c2 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0 @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void t(void) { + switch (1) + { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0.stdout b/src/tools/pg_bsd_indent/tests/label.0.stdout new file mode 100644 index 0000000000..22ec12272a --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0.stdout @@ -0,0 +1,14 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void +t(void) +{ + switch (1) { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.pro b/src/tools/pg_bsd_indent/tests/label.pro new file mode 100644 index 0000000000..75d1fe1a12 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.pro @@ -0,0 +1 @@ +-nut \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/list_head.0 b/src/tools/pg_bsd_indent/tests/list_head.0 new file mode 100644 index 0000000000..35874ebc4e --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0 @@ -0,0 +1,15 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; + + diff --git a/src/tools/pg_bsd_indent/tests/list_head.0.stdout b/src/tools/pg_bsd_indent/tests/list_head.0.stdout new file mode 100644 index 0000000000..2ebcca5730 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0.stdout @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; diff --git a/src/tools/pg_bsd_indent/tests/nsac.0 b/src/tools/pg_bsd_indent/tests/nsac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.0.stdout b/src/tools/pg_bsd_indent/tests/nsac.0.stdout new file mode 100644 index 0000000000..78f3b28757 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double)8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.pro b/src/tools/pg_bsd_indent/tests/nsac.pro new file mode 100644 index 0000000000..6bcbd2b1ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.pro @@ -0,0 +1 @@ +-nsac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0 b/src/tools/pg_bsd_indent/tests/offsetof.0 new file mode 100644 index 0000000000..078db19c29 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0 @@ -0,0 +1,5 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void t(void) { + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0.stdout b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout new file mode 100644 index 0000000000..199bf0fa07 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout @@ -0,0 +1,7 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void +t(void) +{ + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0 b/src/tools/pg_bsd_indent/tests/parens.0 new file mode 100644 index 0000000000..366536ce82 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0 @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) + { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0.stdout b/src/tools/pg_bsd_indent/tests/parens.0.stdout new file mode 100644 index 0000000000..2258f8d2f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0.stdout @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void +similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.pro b/src/tools/pg_bsd_indent/tests/parens.pro new file mode 100644 index 0000000000..e860911a11 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.pro @@ -0,0 +1 @@ +-ts4 -i4 -di12 -Tallocfunc diff --git a/src/tools/pg_bsd_indent/tests/sac.0 b/src/tools/pg_bsd_indent/tests/sac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.0.stdout b/src/tools/pg_bsd_indent/tests/sac.0.stdout new file mode 100644 index 0000000000..1849b28337 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.pro b/src/tools/pg_bsd_indent/tests/sac.pro new file mode 100644 index 0000000000..2b21505c72 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.pro @@ -0,0 +1 @@ +-sac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/struct.0 b/src/tools/pg_bsd_indent/tests/struct.0 new file mode 100644 index 0000000000..83142bfb19 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0 @@ -0,0 +1,21 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + { D, E }, + { F, G } + }; +} + +void u(struct x a) { + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/struct.0.stdout b/src/tools/pg_bsd_indent/tests/struct.0.stdout new file mode 100644 index 0000000000..3861312865 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0.stdout @@ -0,0 +1,23 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + {D, E}, + {F, G} + }; +} + +void +u(struct x a) +{ + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0 b/src/tools/pg_bsd_indent/tests/surplusbad.0 new file mode 100644 index 0000000000..07d07026db --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0 @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout new file mode 100644 index 0000000000..b288970fb9 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.pro b/src/tools/pg_bsd_indent/tests/surplusbad.pro new file mode 100644 index 0000000000..e828c8191c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.pro @@ -0,0 +1 @@ +-bad \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0 b/src/tools/pg_bsd_indent/tests/types_from_file.0 new file mode 100644 index 0000000000..6efca24fe1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0 @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c *z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout new file mode 100644 index 0000000000..8776ca6ba8 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c * z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.list b/src/tools/pg_bsd_indent/tests/types_from_file.list new file mode 100644 index 0000000000..5f733616b1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.list @@ -0,0 +1,2 @@ +b +a \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.pro b/src/tools/pg_bsd_indent/tests/types_from_file.pro new file mode 100644 index 0000000000..39eb911980 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.pro @@ -0,0 +1 @@ +-Utypes_from_file.list \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/wchar.0 b/src/tools/pg_bsd_indent/tests/wchar.0 new file mode 100644 index 0000000000..9910e77857 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; diff --git a/src/tools/pg_bsd_indent/tests/wchar.0.stdout b/src/tools/pg_bsd_indent/tests/wchar.0.stdout new file mode 100644 index 0000000000..92774abfdd --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; commit bc3a18e4ea0b366b4352fc89762470738870b175 Author: Tom Lane <tgl@sss.pgh.pa.us> Date: Thu Feb 9 12:59:52 2023 -0500 Sync pg_bsd_indent's copyright notices with Postgres practice. To avoid confusion, make the copyright notices in these files match the 3-clause form of the BSD license, per the blanket policy update that UC Berkeley issued years ago. Discussion: https://postgr.es/m/20230123011002.fzcaa3krql3mqsfn@awork3.anarazel.de diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 33d016db62..846855d318 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +The FreeBSD originals of the files in this directory bear the +"4-clause" version of the BSD license. We have removed the +"advertising" clauses, as per UC Berkeley's directive here: +ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change +which reads: + +July 22, 1999 + +To All Licensees, Distributors of Any Version of BSD: + +As you know, certain of the Berkeley Software Distribution ("BSD") source +code files require that further distributions of products containing all or +portions of the software, acknowledge within their advertising materials +that such products contain software developed by UC Berkeley and its +contributors. + +Specifically, the provision reads: + +" * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors." + +Effective immediately, licensees and distributors are no longer required to +include the acknowledgement within advertising materials. Accordingly, the +foregoing paragraph of those BSD Unix files containing it is hereby deleted +in its entirety. + +William Hoskins +Director, Office of Technology Licensing +University of California, Berkeley + +---------- + +What follows is the README file as maintained by FreeBSD indent. + +---------- $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index 1c83f57049..b18eab5d39 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index d3a0ecefe9..0024993844 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h index 24c43fa420..6576bef75d 100644 --- a/src/tools/pg_bsd_indent/indent_codes.h +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h index 398784b3f4..917961bd3d 100644 --- a/src/tools/pg_bsd_indent/indent_globs.h +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c index 3ce8bfb70c..4149424294 100644 --- a/src/tools/pg_bsd_indent/io.c +++ b/src/tools/pg_bsd_indent/io.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c index f01596a870..943bf7ce6b 100644 --- a/src/tools/pg_bsd_indent/lexi.c +++ b/src/tools/pg_bsd_indent/lexi.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c index bf6b1697f9..e707da639c 100644 --- a/src/tools/pg_bsd_indent/parse.c +++ b/src/tools/pg_bsd_indent/parse.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c index b0eacac1bb..a9572b39ff 100644 --- a/src/tools/pg_bsd_indent/pr_comment.c +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * commit 52f721604c4c181c625329d099e746c87fa5fd8a Author: Tom Lane <tgl@sss.pgh.pa.us> Date: Thu Feb 9 13:05:20 2023 -0500 Integrate pg_bsd_indent into our build infrastructure. We don't want to build this by default, and certainly not install it by default, but the directory should be subject to cleaning. Also update the Makefile and build directions for in-tree build. This patch doesn't address building it with Meson, but somebody might like to add that. Also, exclude it from pgindent's purview; at least for now, we'll leave it formatted similarly to the FreeBSD original. Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de diff --git a/src/Makefile b/src/Makefile index 79e274a476..94649c36c7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -66,11 +66,13 @@ clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ distclean maintainer-clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ rm -f Makefile.port Makefile.global diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore index 4c5d8dc691..f9393d4452 100644 --- a/src/tools/pg_bsd_indent/.gitignore +++ b/src/tools/pg_bsd_indent/.gitignore @@ -1,9 +1,3 @@ -# Global excludes across all subdirectories -*.o -*.obj -*.exe - -# Local excludes in root directory /pg_bsd_indent /*.out /*.list diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index ee046f36f0..3bd50b4e1c 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -1,33 +1,56 @@ #------------------------------------------------------------------------- # -# Makefile for pg_bsd_indent +# src/tools/pg_bsd_indent/Makefile # -# Copyright (c) 2017, PostgreSQL Global Development Group +# Copyright (c) 2017-2023, PostgreSQL Global Development Group # #------------------------------------------------------------------------- PGFILEDESC = "pg_bsd_indent - indent C code nicely" PGAPPICON = win32 -PROGRAM = pg_bsd_indent -OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) +subdir = src/tools/pg_bsd_indent +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global -# clean junk left behind by "make test" -EXTRA_CLEAN = *.out *.list tests.diff +OBJS = \ + $(WIN32RES) \ + args.o \ + err.o \ + indent.o \ + io.o \ + lexi.o \ + parse.o \ + pr_comment.o -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) +all: pg_bsd_indent -# pgxs.mk assumes too much about what "make check" means, so call it "test" +pg_bsd_indent: $(OBJS) | submake-libpgport + $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pg_bsd_indent$(X) '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +clean distclean maintainer-clean: + rm -f pg_bsd_indent$(X) $(OBJS) + rm -f *.out *.list tests.diff + +# We don't use "make check" because that would insist on building +# all of the surrounding Postgres installation. .PHONY: test -test: $(PROGRAM) +test: pg_bsd_indent @rm -f tests.diff @cp $(srcdir)/tests/*.list . @for testsrc in $(srcdir)/tests/*.0; do \ test=`basename "$$testsrc" .0`; \ - ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ + ./pg_bsd_indent $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ done @cat tests.diff diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 846855d318..0aa3b69fe6 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,36 @@ +src/tools/pg_bsd_indent/README + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, configure the surrounding Postgres source tree, +then run "make" in this directory. +Optionally, run "make test" for some simple sanity checks. + +You'll need to install pg_bsd_indent somewhere in your PATH before +using it. Most likely, if you're a developer, you don't want to +put it in the same place as where the surrounding Postgres build +gets installed. Therefore, do this part with something like + + make install prefix=/usr/local + +TODO: add build support and instructions for Windows + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) +We're not planning to re-indent to Postgres style, because that +would make it difficult to compare to the FreeBSD sources. + +---------- + The FreeBSD originals of the files in this directory bear the "4-clause" version of the BSD license. We have removed the "advertising" clauses, as per UC Berkeley's directive here: diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent deleted file mode 100644 index 85c3dcac1c..0000000000 --- a/src/tools/pg_bsd_indent/README.pg_bsd_indent +++ /dev/null @@ -1,30 +0,0 @@ -pg_bsd_indent - -This is a lightly modified version of the "indent" program maintained -by the FreeBSD project. The modifications are mostly to make it portable -to non-BSD-ish platforms, though we do have one formatting switch we -couldn't convince upstream to take. - -To build it, you will need a Postgres installation, version 9.5 or newer. -(Once built, the program doesn't depend on that installation.) - -To build, just say "make"; or if pg_config from your Postgres installation -isn't in your PATH, say - make PG_CONFIG=path/to/pg_config -Optionally, run "make test" for some simple sanity checks. - -To install, copy pg_bsd_indent to somewhere in your usual PATH. -(If you say "make install", it will try to put it in your Postgres -installation directory, which is most likely not what you want for -long-term use.) - -TODO: add build support and instructions for Windows - - -If you happen to be hacking upon the indent source code, the closest -approximation to the existing indentation style seems to be - - ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c - -although this has by no means been rigorously adhered to. -(What was that saw about the shoemaker's children?) diff --git a/src/tools/pgindent/exclude_file_patterns b/src/tools/pgindent/exclude_file_patterns index f5c8857e31..6405a00511 100644 --- a/src/tools/pgindent/exclude_file_patterns +++ b/src/tools/pgindent/exclude_file_patterns @@ -47,6 +47,10 @@ src/pl/plperl/ppport\.h$ src/pl/plperl/SPI\.c$ src/pl/plperl/Util\.c$ # +# pg_bsd_indent has its own, idiosyncratic indentation style. +# We'll stick to that to permit comparison with the FreeBSD upstream. +src/tools/pg_bsd_indent/.* +# # Exclude any temporary installations that may be in the tree. /tmp_check/ /tmp_install/ commit 22e73a5793872b0dacacd9204353142227870bd2 Author: Tom Lane <tgl@sss.pgh.pa.us> Date: Thu Feb 9 13:13:04 2023 -0500 Fix indentation of multi-line variable initialization expressions. Lines after the first will now be indented one stop compared to the variable declaration itself. They used to be indented the same amount, which was ugly. Thomas Munro and Tom Lane Discussion: https://postgr.es/m/20230120013137.7ky7nl4e4zjorrfa@awork3.anarazel.de diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c index 4149424294..9d64ca1ee5 100644 --- a/src/tools/pg_bsd_indent/io.c +++ b/src/tools/pg_bsd_indent/io.c @@ -201,11 +201,12 @@ dump_line(void) ps.decl_on_line = ps.in_decl; /* if we are in the middle of a * declaration, remember that fact for * proper comment indentation */ - ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be - * indented if we have not - * completed this stmt and if - * we are not in the middle of - * a declaration */ + /* next line should be indented if we have not completed this stmt, and + * either we are not in a declaration or we are in an initialization + * assignment; but not if we're within braces in an initialization, + * because that scenario is handled by other rules. */ + ps.ind_stmt = ps.in_stmt && + (!ps.in_decl || (ps.block_init && ps.block_init_level <= 0)); ps.use_ff = false; ps.dumped_decl_indent = 0; *(e_lab = s_lab) = '\0'; /* reset buffers */
Hi, On 2023-02-09 13:30:30 -0500, Tom Lane wrote: > 0003 lacks meson support (anyone want to help with that?) I'll give it a go, unless somebody else wants to. Do we expect pg_bsd_indent to build / work on windows, right now? If it doesn't, do we want to make that a hard requirement? I'll have CI test that, once I added meson support. > I'd anticipate pushing 0001-0003 shortly but holding 0004 until we are ready > to do the post-March-CF pgindent run. (Come to think of it, 0004 had > probably better include a pg_bsd_indent version bump too.) How large is the diff that creates? If it's not super-widespread, it might be ok to do that earlier. I wouldn't mind not seeing that uglyness every time I run pgindent on a patch... Although I guess post-March-CF isn't that far away at this point :) Greetings, Andres Freund
Andres Freund <andres@anarazel.de> writes: > On 2023-02-09 13:30:30 -0500, Tom Lane wrote: >> 0003 lacks meson support (anyone want to help with that?) > I'll give it a go, unless somebody else wants to. Thanks. > Do we expect pg_bsd_indent to build / work on windows, right now? It would be desirable, for sure. I've not noticed anything remarkably unportable in the code, so probably it's just a matter of getting the build infrastructure to build it. I suppose that we aren't going to update the src/tools/msvc scripts anymore, so getting meson to handle it should be enough?? >> I'd anticipate pushing 0001-0003 shortly but holding 0004 until we are ready >> to do the post-March-CF pgindent run. (Come to think of it, 0004 had >> probably better include a pg_bsd_indent version bump too.) > How large is the diff that creates? If it's not super-widespread, it might be > ok to do that earlier. It wasn't that big; I posted it in the thread discussing that change. I think the real issue might just be that, assuming we bump the pg_bsd_indent version number, that in itself would force interested committers to update their copy Right Now. I'd rather give a little notice. regards, tom lane
Hi, On 2023-02-09 13:02:02 -0800, Andres Freund wrote: > On 2023-02-09 13:30:30 -0500, Tom Lane wrote: > > 0003 lacks meson support (anyone want to help with that?) > > I'll give it a go, unless somebody else wants to. Did that in the attached. I didn't convert the test though, due to the duplicating it'd create. Perhaps we should just move it to a shell script? Or maybe it just doesn't matter enough to bother with? > Do we expect pg_bsd_indent to build / work on windows, right now? If it > doesn't, do we want to make that a hard requirement? > I'll have CI test that, once I added meson support. It doesn't build as-is with msvc, but does build with mingw. Failure: https://cirrus-ci.com/task/6290206869946368?logs=build#L1573 "cl" "-Isrc\tools/pg_bsd_indent\pg_bsd_indent.exe.p" "-Isrc\tools/pg_bsd_indent" "-I..\src\tools\pg_bsd_indent" "-Isrc\include""-I..\src\include" "-Ic:\openssl\1.1\include" "-I..\src\include\port\win32" "-I..\src\include\port\win32_msvc""/MDd" "/nologo" "/showIncludes" "/utf-8" "/W2" "/Od" "/Zi" "/DWIN32" "/DWINDOWS" "/D__WINDOWS__""/D__WIN32__" "/D_CRT_SECURE_NO_DEPRECATE" "/D_CRT_NONSTDC_NO_DEPRECATE" "/wd4018" "/wd4244" "/wd4273" "/wd4101""/wd4102" "/wd4090" "/wd4267" "/Fdsrc\tools/pg_bsd_indent\pg_bsd_indent.exe.p\args.c.pdb" /Fosrc/tools/pg_bsd_indent/pg_bsd_indent.exe.p/args.c.obj"/c" ../src/tools/pg_bsd_indent/args.c ../src/tools/pg_bsd_indent/args.c(179): error C2065: 'PATH_MAX': undeclared identifier ../src/tools/pg_bsd_indent/args.c(179): error C2057: expected constant expression ../src/tools/pg_bsd_indent/args.c(179): error C2466: cannot allocate an array of constant size 0 ../src/tools/pg_bsd_indent/args.c(179): error C2133: 'fname': unknown size ../src/tools/pg_bsd_indent/args.c(183): warning C4034: sizeof returns 0 ../src/tools/pg_bsd_indent/args.c(185): warning C4034: sizeof returns 0 [1557/2161] Compiling C object src/tools/pg_bsd_indent/pg_bsd_indent.exe.p/err.c.obj [1558/2161] Precompiling header src/interfaces/ecpg/ecpglib/libecpg.dll.p/meson_pch-c.c [1559/2161] Compiling C object src/tools/pg_bsd_indent/pg_bsd_indent.exe.p/indent.c.obj FAILED: src/tools/pg_bsd_indent/pg_bsd_indent.exe.p/indent.c.obj "cl" "-Isrc\tools/pg_bsd_indent\pg_bsd_indent.exe.p" "-Isrc\tools/pg_bsd_indent" "-I..\src\tools\pg_bsd_indent" "-Isrc\include""-I..\src\include" "-Ic:\openssl\1.1\include" "-I..\src\include\port\win32" "-I..\src\include\port\win32_msvc""/MDd" "/nologo" "/showIncludes" "/utf-8" "/W2" "/Od" "/Zi" "/DWIN32" "/DWINDOWS" "/D__WINDOWS__""/D__WIN32__" "/D_CRT_SECURE_NO_DEPRECATE" "/D_CRT_NONSTDC_NO_DEPRECATE" "/wd4018" "/wd4244" "/wd4273" "/wd4101""/wd4102" "/wd4090" "/wd4267" "/Fdsrc\tools/pg_bsd_indent\pg_bsd_indent.exe.p\indent.c.pdb" /Fosrc/tools/pg_bsd_indent/pg_bsd_indent.exe.p/indent.c.obj"/c" ../src/tools/pg_bsd_indent/indent.c ../src/tools/pg_bsd_indent/indent.c(63): error C2065: 'MAXPATHLEN': undeclared identifier ../src/tools/pg_bsd_indent/indent.c(63): error C2057: expected constant expression ../src/tools/pg_bsd_indent/indent.c(63): error C2466: cannot allocate an array of constant size 0 This specific issue at least should be easily fixable. Freebsd emits a compiler warning: [21:37:50.909] In file included from ../src/tools/pg_bsd_indent/indent.c:54: [21:37:50.909] ../src/tools/pg_bsd_indent/indent.h:31:9: warning: 'nitems' macro redefined [-Wmacro-redefined] [21:37:50.909] #define nitems(array) (sizeof (array) / sizeof (array[0])) [21:37:50.909] ^ [21:37:50.909] /usr/include/sys/param.h:306:9: note: previous definition is here [21:37:50.909] #define nitems(x) (sizeof((x)) / sizeof((x)[0])) [21:37:50.909] ^ [21:37:50.911] 1 warning generated. To we really want to require users to install pg_bsd_indent into PATH? Seems like we ought to have a build target to invoke pgindent with a path to pg_bsd_indent or such? But I guess we can address that later. Independent of this specific patch: You seem to be generating your patch series by invoking git show and redirecting that to a file? How do you apply a series of such patches, while maintaining the commit messages? When git format-patch is used, I can just use git am, but that doesn't work with your patch series. Greetings, Andres Freund
Attachment
Andres Freund <andres@anarazel.de> writes: > Did that in the attached. Thanks. > I didn't convert the test though, due to the duplicating it'd create. Perhaps > we should just move it to a shell script? Or maybe it just doesn't matter > enough to bother with? We could move it to a shell script perhaps, but that seems pretty low-priority. > It doesn't build as-is with msvc, but does build with mingw. Failure: > https://cirrus-ci.com/task/6290206869946368?logs=build#L1573 Thanks, I'll take a look at these things. > To we really want to require users to install pg_bsd_indent into PATH? Seems > like we ought to have a build target to invoke pgindent with a path to > pg_bsd_indent or such? But I guess we can address that later. For the moment I was just interested in maintaining the current workflow. I know people muttered about having some sort of build target that'd indent the whole tree from scratch after building pg_bsd_indent, but it's not very clear to me how that'd work with e.g. VPATH configurations. (I think you can already tell pgindent to use a specific pg_bsd_indent, if your gripe is just about wanting to use a prebuilt copy that you don't want to keep in PATH for some reason.) > Independent of this specific patch: You seem to be generating your patch > series by invoking git show and redirecting that to a file? Yeah, it's pretty low-tech. I'm not in the habit of posting multi-patch series very often, so I haven't really bothered to use format-patch. (I gave up on "git am" long ago as being too fragile, and always use good ol' "patch" to apply patches, so I don't think about things like whether it'd automatically absorb commit messages. I pretty much never use anyone else's commit message verbatim anyway ...) regards, tom lane
Hi, On 2023-02-09 13:55:32 -0800, Andres Freund wrote: > ../src/tools/pg_bsd_indent/args.c(179): error C2065: 'PATH_MAX': undeclared identifier > ../src/tools/pg_bsd_indent/args.c(179): error C2057: expected constant expression > ../src/tools/pg_bsd_indent/args.c(179): error C2466: cannot allocate an array of constant size 0 > ../src/tools/pg_bsd_indent/args.c(179): error C2133: 'fname': unknown size > ../src/tools/pg_bsd_indent/args.c(183): warning C4034: sizeof returns 0 > ../src/tools/pg_bsd_indent/args.c(185): warning C4034: sizeof returns 0 > [1557/2161] Compiling C object src/tools/pg_bsd_indent/pg_bsd_indent.exe.p/err.c.obj > [1558/2161] Precompiling header src/interfaces/ecpg/ecpglib/libecpg.dll.p/meson_pch-c.c > [1559/2161] Compiling C object src/tools/pg_bsd_indent/pg_bsd_indent.exe.p/indent.c.obj > FAILED: src/tools/pg_bsd_indent/pg_bsd_indent.exe.p/indent.c.obj > "cl" "-Isrc\tools/pg_bsd_indent\pg_bsd_indent.exe.p" "-Isrc\tools/pg_bsd_indent" "-I..\src\tools\pg_bsd_indent" "-Isrc\include""-I..\src\include" "-Ic:\openssl\1.1\include" "-I..\src\include\port\win32" "-I..\src\include\port\win32_msvc""/MDd" "/nologo" "/showIncludes" "/utf-8" "/W2" "/Od" "/Zi" "/DWIN32" "/DWINDOWS" "/D__WINDOWS__""/D__WIN32__" "/D_CRT_SECURE_NO_DEPRECATE" "/D_CRT_NONSTDC_NO_DEPRECATE" "/wd4018" "/wd4244" "/wd4273" "/wd4101""/wd4102" "/wd4090" "/wd4267" "/Fdsrc\tools/pg_bsd_indent\pg_bsd_indent.exe.p\indent.c.pdb" /Fosrc/tools/pg_bsd_indent/pg_bsd_indent.exe.p/indent.c.obj"/c" ../src/tools/pg_bsd_indent/indent.c > ../src/tools/pg_bsd_indent/indent.c(63): error C2065: 'MAXPATHLEN': undeclared identifier > ../src/tools/pg_bsd_indent/indent.c(63): error C2057: expected constant expression > ../src/tools/pg_bsd_indent/indent.c(63): error C2466: cannot allocate an array of constant size 0 > > This specific issue at least should be easily fixable. The trivial fix of using MAXPGPATH made it build, without warnings. That doesn't say anything about actually working. So I guess porting the test would make sense. Opinions on whether it would make sense as a shell script? Greetings, Andres Freund
Andres Freund <andres@anarazel.de> writes: > The trivial fix of using MAXPGPATH made it build, without warnings. That > doesn't say anything about actually working. So I guess porting the test would > make sense. > Opinions on whether it would make sense as a shell script? Hmmm .. a shell script would be fine by me, but it won't help in testing a Windows build. Maybe we need to make it a Perl script? BTW, the attachments to your previous message are identical to what I previously posted --- did you attach the wrong set of diffs? regards, tom lane
Hi, On 2023-02-09 17:19:22 -0500, Tom Lane wrote: > Andres Freund <andres@anarazel.de> writes: > > The trivial fix of using MAXPGPATH made it build, without warnings. That > > doesn't say anything about actually working. So I guess porting the test would > > make sense. > > > Opinions on whether it would make sense as a shell script? > > Hmmm .. a shell script would be fine by me, but it won't help in > testing a Windows build. Maybe we need to make it a Perl script? At least for casual testing a shell script actually mostly works, due to git it's easy enough to have a sh.exe around... Not something I'd necessarily want to make a hard dependency, but for something like this it might suffice. Of course perl would be more dependable... > BTW, the attachments to your previous message are identical to what > I previously posted --- did you attach the wrong set of diffs? I attached an extra patch, in addition to yours. I also attached yours so that cfbot could continue to work, if you registered this. Greetings, Andres Freund
Andres Freund <andres@anarazel.de> writes: > On 2023-02-09 17:19:22 -0500, Tom Lane wrote: >> Hmmm .. a shell script would be fine by me, but it won't help in >> testing a Windows build. Maybe we need to make it a Perl script? > At least for casual testing a shell script actually mostly works, due to git > it's easy enough to have a sh.exe around... Not something I'd necessarily want > to make a hard dependency, but for something like this it might suffice. Of > course perl would be more dependable... Yeah, also less question about whether it works on Windows. I'll see about moving that into Perl. It's short enough. >> BTW, the attachments to your previous message are identical to what >> I previously posted --- did you attach the wrong set of diffs? > I attached an extra patch, in addition to yours. D'oh, I didn't notice that :-( > I also attached yours so that > cfbot could continue to work, if you registered this. I thought about registering it, but that won't teach us anything unless we make it built-by-default, which was not my intention. I guess we could temporarily include it in the build. regards, tom lane
Hi, On 2023-02-09 18:19:06 -0500, Tom Lane wrote: > Andres Freund <andres@anarazel.de> writes: > > On 2023-02-09 17:19:22 -0500, Tom Lane wrote: > >> Hmmm .. a shell script would be fine by me, but it won't help in > >> testing a Windows build. Maybe we need to make it a Perl script? > > > At least for casual testing a shell script actually mostly works, due to git > > it's easy enough to have a sh.exe around... Not something I'd necessarily want > > to make a hard dependency, but for something like this it might suffice. Of > > course perl would be more dependable... > > Yeah, also less question about whether it works on Windows. > I'll see about moving that into Perl. It's short enough. Cool. > > I also attached yours so that > > cfbot could continue to work, if you registered this. > > I thought about registering it, but that won't teach us anything unless > we make it built-by-default, which was not my intention. I guess we > could temporarily include it in the build. The meson patch I sent did build it by default, that's why I saw the windows failure and the freebsd warnings. If we don't want that, we'd need to add build_by_default: false I'm fine either way. It's barely noticeable compared to the rest of postgres. Greetings, Andres Freund
Andres Freund <andres@anarazel.de> writes: > On 2023-02-09 18:19:06 -0500, Tom Lane wrote: >> I thought about registering it, but that won't teach us anything unless >> we make it built-by-default, which was not my intention. I guess we >> could temporarily include it in the build. > The meson patch I sent did build it by default, that's why I saw the windows > failure and the freebsd warnings. If we don't want that, we'd need to add > build_by_default: false > I'm fine either way. It's barely noticeable compared to the rest of postgres. Yeah, build-by-default isn't really a big deal. Install-by-default is more of a problem... regards, tom lane
On 2023-02-09 19:20:37 -0500, Tom Lane wrote: > Andres Freund <andres@anarazel.de> writes: > > I'm fine either way. It's barely noticeable compared to the rest of postgres. > > Yeah, build-by-default isn't really a big deal. Install-by-default > is more of a problem... Perhaps we should install it, just not in bin/, but alongside pgxs/, similar to pg_regress et al?
Andres Freund <andres@anarazel.de> writes: > Perhaps we should install it, just not in bin/, but alongside pgxs/, similar > to pg_regress et al? For my own purposes, I really don't want it anywhere in the --prefix tree. That's not necessarily present when I'm using the program. (Hmm, clarify: it wouldn't matter if install sticks it under pgxs, but I don't want to be forced to use it from there.) regards, tom lane
Here's a v3 of this patchset, incorporating your meson fixes as well as patches for the portability problems you noted. I ended up converting the test infrastructure into a TAP test, which kind of feels like overkill; but the Meson system doesn't seem to provide any lower-overhead way to run a test. I've not touched the issue of whether and where to install pg_bsd_indent; for now, neither build system will do so. Also, for now both build systems *will* run tests on it, although I'm not sure if plugging it into "make check-world" is enough to cause the cfbot to do so, and I'm pretty sure that the buildfarm won't notice that. I'll let the cfbot loose on this, and if it runs the tests successfully I plan to go ahead and push. We can resolve the installation question later. We might want to back off testing too once we're satisfied about portability. (I left out the 0004 declaration-formatting patch for now, btw.) regards, tom lane From 55d1373fb0f7df6745ef8c34274bc82cb84d15d0 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 14:06:36 -0500 Subject: [PATCH v3 1/3] Import pg_bsd_indent sources. This brings in an exact copy of the pg_bsd_indent repo as of commit d301442799cea44e5ccb04331afc537764ec77c5 (2020-12-28). Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de --- src/tools/pg_bsd_indent/.gitignore | 10 + src/tools/pg_bsd_indent/Makefile | 35 + src/tools/pg_bsd_indent/README | 100 ++ src/tools/pg_bsd_indent/README.pg_bsd_indent | 30 + src/tools/pg_bsd_indent/args.c | 354 +++++ src/tools/pg_bsd_indent/err.c | 67 + src/tools/pg_bsd_indent/err.h | 45 + src/tools/pg_bsd_indent/indent.1 | 618 ++++++++ src/tools/pg_bsd_indent/indent.c | 1279 +++++++++++++++++ src/tools/pg_bsd_indent/indent.h | 51 + src/tools/pg_bsd_indent/indent_codes.h | 75 + src/tools/pg_bsd_indent/indent_globs.h | 343 +++++ src/tools/pg_bsd_indent/io.c | 608 ++++++++ src/tools/pg_bsd_indent/lexi.c | 724 ++++++++++ src/tools/pg_bsd_indent/parse.c | 342 +++++ src/tools/pg_bsd_indent/pr_comment.c | 358 +++++ src/tools/pg_bsd_indent/tests/binary.0 | 9 + src/tools/pg_bsd_indent/tests/binary.0.stdout | 11 + src/tools/pg_bsd_indent/tests/comments.0 | 52 + .../pg_bsd_indent/tests/comments.0.stdout | 60 + src/tools/pg_bsd_indent/tests/comments.pro | 1 + src/tools/pg_bsd_indent/tests/cppelsecom.0 | 7 + .../pg_bsd_indent/tests/cppelsecom.0.stdout | 7 + src/tools/pg_bsd_indent/tests/declarations.0 | 79 + .../pg_bsd_indent/tests/declarations.0.stdout | 73 + src/tools/pg_bsd_indent/tests/elsecomment.0 | 42 + .../pg_bsd_indent/tests/elsecomment.0.stdout | 47 + src/tools/pg_bsd_indent/tests/elsecomment.pro | 1 + src/tools/pg_bsd_indent/tests/enum.0 | 6 + src/tools/pg_bsd_indent/tests/enum.0.stdout | 5 + src/tools/pg_bsd_indent/tests/f_decls.0 | 27 + .../pg_bsd_indent/tests/f_decls.0.stdout | 30 + src/tools/pg_bsd_indent/tests/float.0 | 6 + src/tools/pg_bsd_indent/tests/float.0.stdout | 8 + src/tools/pg_bsd_indent/tests/label.0 | 13 + src/tools/pg_bsd_indent/tests/label.0.stdout | 14 + src/tools/pg_bsd_indent/tests/label.pro | 1 + src/tools/pg_bsd_indent/tests/list_head.0 | 15 + .../pg_bsd_indent/tests/list_head.0.stdout | 13 + src/tools/pg_bsd_indent/tests/nsac.0 | 4 + src/tools/pg_bsd_indent/tests/nsac.0.stdout | 6 + src/tools/pg_bsd_indent/tests/nsac.pro | 1 + src/tools/pg_bsd_indent/tests/offsetof.0 | 5 + .../pg_bsd_indent/tests/offsetof.0.stdout | 7 + src/tools/pg_bsd_indent/tests/parens.0 | 26 + src/tools/pg_bsd_indent/tests/parens.0.stdout | 26 + src/tools/pg_bsd_indent/tests/parens.pro | 1 + src/tools/pg_bsd_indent/tests/sac.0 | 4 + src/tools/pg_bsd_indent/tests/sac.0.stdout | 6 + src/tools/pg_bsd_indent/tests/sac.pro | 1 + src/tools/pg_bsd_indent/tests/struct.0 | 21 + src/tools/pg_bsd_indent/tests/struct.0.stdout | 23 + src/tools/pg_bsd_indent/tests/surplusbad.0 | 9 + .../pg_bsd_indent/tests/surplusbad.0.stdout | 9 + src/tools/pg_bsd_indent/tests/surplusbad.pro | 1 + .../pg_bsd_indent/tests/types_from_file.0 | 3 + .../tests/types_from_file.0.stdout | 3 + .../pg_bsd_indent/tests/types_from_file.list | 2 + .../pg_bsd_indent/tests/types_from_file.pro | 1 + src/tools/pg_bsd_indent/tests/wchar.0 | 6 + src/tools/pg_bsd_indent/tests/wchar.0.stdout | 6 + 61 files changed, 5737 insertions(+) create mode 100644 src/tools/pg_bsd_indent/.gitignore create mode 100644 src/tools/pg_bsd_indent/Makefile create mode 100644 src/tools/pg_bsd_indent/README create mode 100644 src/tools/pg_bsd_indent/README.pg_bsd_indent create mode 100644 src/tools/pg_bsd_indent/args.c create mode 100644 src/tools/pg_bsd_indent/err.c create mode 100644 src/tools/pg_bsd_indent/err.h create mode 100644 src/tools/pg_bsd_indent/indent.1 create mode 100644 src/tools/pg_bsd_indent/indent.c create mode 100644 src/tools/pg_bsd_indent/indent.h create mode 100644 src/tools/pg_bsd_indent/indent_codes.h create mode 100644 src/tools/pg_bsd_indent/indent_globs.h create mode 100644 src/tools/pg_bsd_indent/io.c create mode 100644 src/tools/pg_bsd_indent/lexi.c create mode 100644 src/tools/pg_bsd_indent/parse.c create mode 100644 src/tools/pg_bsd_indent/pr_comment.c create mode 100644 src/tools/pg_bsd_indent/tests/binary.0 create mode 100644 src/tools/pg_bsd_indent/tests/binary.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/comments.0 create mode 100644 src/tools/pg_bsd_indent/tests/comments.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/comments.pro create mode 100644 src/tools/pg_bsd_indent/tests/cppelsecom.0 create mode 100644 src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/declarations.0 create mode 100644 src/tools/pg_bsd_indent/tests/declarations.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.0 create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.pro create mode 100644 src/tools/pg_bsd_indent/tests/enum.0 create mode 100644 src/tools/pg_bsd_indent/tests/enum.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/f_decls.0 create mode 100644 src/tools/pg_bsd_indent/tests/f_decls.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/float.0 create mode 100644 src/tools/pg_bsd_indent/tests/float.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/label.0 create mode 100644 src/tools/pg_bsd_indent/tests/label.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/label.pro create mode 100644 src/tools/pg_bsd_indent/tests/list_head.0 create mode 100644 src/tools/pg_bsd_indent/tests/list_head.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/nsac.0 create mode 100644 src/tools/pg_bsd_indent/tests/nsac.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/nsac.pro create mode 100644 src/tools/pg_bsd_indent/tests/offsetof.0 create mode 100644 src/tools/pg_bsd_indent/tests/offsetof.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/parens.0 create mode 100644 src/tools/pg_bsd_indent/tests/parens.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/parens.pro create mode 100644 src/tools/pg_bsd_indent/tests/sac.0 create mode 100644 src/tools/pg_bsd_indent/tests/sac.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/sac.pro create mode 100644 src/tools/pg_bsd_indent/tests/struct.0 create mode 100644 src/tools/pg_bsd_indent/tests/struct.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.0 create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.pro create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.0 create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.list create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.pro create mode 100644 src/tools/pg_bsd_indent/tests/wchar.0 create mode 100644 src/tools/pg_bsd_indent/tests/wchar.0.stdout diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore new file mode 100644 index 0000000000..4c5d8dc691 --- /dev/null +++ b/src/tools/pg_bsd_indent/.gitignore @@ -0,0 +1,10 @@ +# Global excludes across all subdirectories +*.o +*.obj +*.exe + +# Local excludes in root directory +/pg_bsd_indent +/*.out +/*.list +/tests.diff diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile new file mode 100644 index 0000000000..ee046f36f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/Makefile @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------- +# +# Makefile for pg_bsd_indent +# +# Copyright (c) 2017, PostgreSQL Global Development Group +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pg_bsd_indent - indent C code nicely" +PGAPPICON = win32 + +PROGRAM = pg_bsd_indent +OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) + +# clean junk left behind by "make test" +EXTRA_CLEAN = *.out *.list tests.diff + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) + +# pgxs.mk assumes too much about what "make check" means, so call it "test" +.PHONY: test + +test: $(PROGRAM) + @rm -f tests.diff + @cp $(srcdir)/tests/*.list . + @for testsrc in $(srcdir)/tests/*.0; do \ + test=`basename "$$testsrc" .0`; \ + ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ + diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ + done + @cat tests.diff + @test '!' -s tests.diff + @echo Tests complete. diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README new file mode 100644 index 0000000000..33d016db62 --- /dev/null +++ b/src/tools/pg_bsd_indent/README @@ -0,0 +1,100 @@ + + $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ + +This is the C indenter, it originally came from the University of Illinois +via some distribution tape for PDP-11 Unix. It has subsequently been +hacked upon by James Gosling @ CMU. It isn't very pretty, and really needs +to be completely redone, but it is probably the nicest C pretty printer +around. + +Further additions to provide "Kernel Normal Form" were contributed +by the folks at Sun Microsystems. + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +> From mnetor!yunexus!oz@uunet.UU.NET Wed Mar 9 15:30:55 1988 +> Date: Tue, 8 Mar 88 18:36:25 EST +> From: yunexus!oz@uunet.UU.NET (Ozan Yigit) +> To: bostic@okeeffe.berkeley.edu +> Cc: ccvaxa!willcox@uunet.UU.NET, jag@sun.com, rsalz@uunet.UU.NET +> In-Reply-To: Keith Bostic's message of Tue, 16 Feb 88 16:09:06 PST +> Subject: Re: Indent... + +Thank you for your response about indent. I was wrong in my original +observation (or mis-observation :-). UCB did keep the Illinois +copyright intact. + +The issue still is whether we can distribute indent, and if we can, which +version. David Willcox (the author) states that: + +| Several people have asked me on what basis I claim that indent is in +| the public domain. I knew I would be sorry I made that posting. +| +| Some history. Way back in 1976, the project I worked on at the +| University of Illinois Center for Advanced Computation had a huge +| battle about how to format C code. After about a week of fighting, I +| got disgusted and wrote a program, which I called indent, to reformat C +| code. It had a bunch of different options that would let you format +| the output the way you liked. In particular, all of the different +| formats being championed were supported. +| +| It was my first big C program. It was ugly. It wasn't designed, it +| just sort of grew. But it pretty much worked, and it stopped most of +| the fighting. +| +| As a matter of form, I included a University of Illinois Copyright +| notice. However, my understanding was that, since the work was done +| on an ARPA contract, it was in the public domain. +| +| Time passed. Some years later, indent showed up on one of the early +| emacs distributions. +| +| Later still, someone from UC Berkeley called the UofI and asked if +| indent was in the public domain. They wanted to include it in their +| UNIX distributions, along with the emacs stuff. I was no longer at the +| UofI, but Rob Kolstad, who was, asked me about it. I told him I didn't +| care if they used it, and since then it has been on the BSD distributions. +| +| Somewhere along the way, several other unnamed people have had their +| hands in it. It was converted to understand version 7 C. (The +| original was version 6.) It was converted from its original filter +| interface to its current "blow away the user's file" interface. +| The $HOME/.indent.pro file parsing was added. Some more formatting +| options were added. +| +| The source I have right now has two copyright notices. One is the +| original from the UofI. One is from Berkeley. +| +| I am not a lawyer, and I certainly do not understand copyright law. As +| far as I am concerned, the bulk of this program, everything covered by +| the UofI copyright, is in the public domain, and worth every penny. +| Berkeley's copyright probably should only cover their changes, and I +| don't know their feelings about sending it out. + +In any case, there appears to be none at UofI to clarify/and change +that copyright, but I am confident (based on the statements of its +author) that the code, as it stands with its copyright, is +distributable, and will not cause any legal problems. + +Hence, the issue reduces to *which* one to distribute through +comp.sources.unix. I would suggest that with the permission of you +folks (given that you have parts copyrighted), we distribute the 4.3 +version of indent, which appears to be the most up-to-date version. I +happen to have just about every known version of indent, including the +very original submission from the author to a unix tape, later the +G-Emacs version, any 4.n version, sun version and the Unipress +version. I still think we should not have to "go-back-in-time" and +re-do all the work you people have done. + +I hope to hear from you as to what you think about this. You may of +course send 4.3 version to the moderator directly, or you can let me +know of your permission, and I will send the sources, or you can let +me know that 4.3 version is off-limits, in which case we would probably +have to revert to an older version. One way or another, I hope to get +a version of indent to comp.sources.unix. + +regards.. oz + +cc: ccvaxa!willcox + sun.com!jar + uunet!rsalz + diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent new file mode 100644 index 0000000000..85c3dcac1c --- /dev/null +++ b/src/tools/pg_bsd_indent/README.pg_bsd_indent @@ -0,0 +1,30 @@ +pg_bsd_indent + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, you will need a Postgres installation, version 9.5 or newer. +(Once built, the program doesn't depend on that installation.) + +To build, just say "make"; or if pg_config from your Postgres installation +isn't in your PATH, say + make PG_CONFIG=path/to/pg_config +Optionally, run "make test" for some simple sanity checks. + +To install, copy pg_bsd_indent to somewhere in your usual PATH. +(If you say "make install", it will try to put it in your Postgres +installation directory, which is most likely not what you want for +long-term use.) + +TODO: add build support and instructions for Windows + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c new file mode 100644 index 0000000000..1c83f57049 --- /dev/null +++ b/src/tools/pg_bsd_indent/args.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include <ctype.h> +#include <err.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +#define INDENT_VERSION "2.1.1" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +static void scan_profile(FILE *); + +#define KEY_FILE 5 /* only used for args */ +#define VERSION 6 /* only used for args */ + +const char *option_source = "?"; + +void add_typedefs_from_file(const char *str); + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + const char *p_name; /* name, e.g. -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + {"T", PRO_SPECIAL, 0, KEY, 0}, + {"U", PRO_SPECIAL, 0, KEY_FILE, 0}, + {"-version", PRO_SPECIAL, 0, VERSION, 0}, + {"P", PRO_SPECIAL, 0, IGN, 0}, + {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation}, + {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop}, + {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations}, + {"bap", PRO_BOOL, false, ON, &blanklines_after_procs}, + {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments}, + {"bc", PRO_BOOL, true, OFF, &ps.leave_comma}, + {"bl", PRO_BOOL, true, OFF, &btype_2}, + {"br", PRO_BOOL, true, ON, &btype_2}, + {"bs", PRO_BOOL, false, ON, &Bill_Shannon}, + {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline}, + {"cd", PRO_INT, 0, 0, &ps.decl_com_ind}, + {"ce", PRO_BOOL, true, ON, &cuddle_else}, + {"ci", PRO_INT, 0, 0, &continuation_indent}, + {"cli", PRO_SPECIAL, 0, CLI, 0}, + {"cp", PRO_INT, 0, 0, &else_endif_com_ind}, + {"c", PRO_INT, 33, 0, &ps.com_ind}, + {"di", PRO_INT, 16, 0, &ps.decl_indent}, + {"dj", PRO_BOOL, false, ON, &ps.ljust_decl}, + {"d", PRO_INT, 0, 0, &ps.unindent_displace}, + {"eei", PRO_BOOL, false, ON, &extra_expression_indent}, + {"ei", PRO_BOOL, true, ON, &ps.else_if}, + {"fbs", PRO_BOOL, true, ON, &function_brace_split}, + {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, + {"fcb", PRO_BOOL, true, ON, &format_block_comments}, + {"ip", PRO_BOOL, true, ON, &ps.indent_parameters}, + {"i", PRO_INT, 8, 0, &ps.ind_size}, + {"lc", PRO_INT, 0, 0, &block_comment_max_col}, + {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent}, + {"lpl", PRO_BOOL, false, ON, &lineup_to_parens_always}, + {"lp", PRO_BOOL, true, ON, &lineup_to_parens}, + {"l", PRO_INT, 78, 0, &max_col}, + {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation}, + {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop}, + {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations}, + {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs}, + {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments}, + {"nbc", PRO_BOOL, true, ON, &ps.leave_comma}, + {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon}, + {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline}, + {"nce", PRO_BOOL, true, OFF, &cuddle_else}, + {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl}, + {"neei", PRO_BOOL, false, OFF, &extra_expression_indent}, + {"nei", PRO_BOOL, true, OFF, &ps.else_if}, + {"nfbs", PRO_BOOL, true, OFF, &function_brace_split}, + {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments}, + {"nfcb", PRO_BOOL, true, OFF, &format_block_comments}, + {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters}, + {"nlpl", PRO_BOOL, false, OFF, &lineup_to_parens_always}, + {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens}, + {"npcs", PRO_BOOL, false, OFF, &proc_calls_space}, + {"npro", PRO_SPECIAL, 0, IGN, 0}, + {"npsl", PRO_BOOL, true, OFF, &procnames_start_line}, + {"nsac", PRO_BOOL, false, OFF, &space_after_cast}, + {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, + {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, + {"ntpg", PRO_BOOL, false, OFF, &postgres_tab_rules}, + {"nut", PRO_BOOL, true, OFF, &use_tabs}, + {"nv", PRO_BOOL, false, OFF, &verbose}, + {"pcs", PRO_BOOL, false, ON, &proc_calls_space}, + {"psl", PRO_BOOL, true, ON, &procnames_start_line}, + {"sac", PRO_BOOL, false, ON, &space_after_cast}, + {"sc", PRO_BOOL, true, ON, &star_comment_cont}, + {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines}, + {"st", PRO_SPECIAL, 0, STDIN, 0}, + {"ta", PRO_BOOL, false, ON, &auto_typedefs}, + {"tpg", PRO_BOOL, false, ON, &postgres_tab_rules}, + {"ts", PRO_INT, 8, 0, &tabsize}, + {"ut", PRO_BOOL, true, ON, &use_tabs}, + {"v", PRO_BOOL, false, ON, &verbose}, + /* whew! */ + {0, 0, 0, 0, 0} +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +void +set_profile(const char *profile_name) +{ + FILE *f; + char fname[PATH_MAX]; + static char prof[] = ".indent.pro"; + + if (profile_name == NULL) + snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); + else + snprintf(fname, sizeof(fname), "%s", profile_name + 2); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +static void +scan_profile(FILE *f) +{ + int comment, i; + char *p; + char buf[BUFSIZ]; + + while (1) { + p = buf; + comment = 0; + while ((i = getc(f)) != EOF) { + if (i == '*' && !comment && p > buf && p[-1] == '/') { + comment = p - buf; + *p++ = i; + } else if (i == '/' && comment && p > buf && p[-1] == '*') { + p = buf + comment - 1; + comment = 0; + } else if (isspace((unsigned char)i)) { + if (p > buf && !comment) + break; + } else { + *p++ = i; + } + } + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +static const char * +eqin(const char *s1, const char *s2) +{ + while (*s1) { + if (*s1++ != *s2++) + return (NULL); + } + return (s2); +} + +/* + * Set the defaults. + */ +void +set_defaults(void) +{ + struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL) + *p->p_obj = p->p_default; +} + +void +set_option(char *arg) +{ + struct pro *p; + const char *param_start; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL) + goto found; + errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == NULL) + input = stdin; + if (output == NULL) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + add_typename(param_start); + break; + + case KEY_FILE: + if (*param_start == 0) + goto need_param; + add_typedefs_from_file(param_start); + break; + + case VERSION: + printf("pg_bsd_indent %s (based on FreeBSD indent)\n", INDENT_VERSION); + exit(0); + + default: + errx(1, "set_option: internal error: p_special %d", p->p_special); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit((unsigned char)*param_start)) { + need_param: + errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name); + } + *p->p_obj = atoi(param_start); + break; + + default: + errx(1, "set_option: internal error: p_type %d", p->p_type); + } +} + +void +add_typedefs_from_file(const char *str) +{ + FILE *file; + char line[BUFSIZ]; + + if ((file = fopen(str, "r")) == NULL) { + fprintf(stderr, "indent: cannot open file %s\n", str); + exit(1); + } + while ((fgets(line, BUFSIZ, file)) != NULL) { + /* Remove trailing whitespace */ + line[strcspn(line, " \t\n\r")] = '\0'; + add_typename(line); + } + fclose(file); +} diff --git a/src/tools/pg_bsd_indent/err.c b/src/tools/pg_bsd_indent/err.c new file mode 100644 index 0000000000..807319334b --- /dev/null +++ b/src/tools/pg_bsd_indent/err.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This is cut down to just the minimum that we need to build indent. + */ +#include "c.h" + +#include <err.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void +err(int eval, const char *fmt, ...) +{ + int code = errno; + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); + va_end(ap); + exit(eval); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(eval); +} diff --git a/src/tools/pg_bsd_indent/err.h b/src/tools/pg_bsd_indent/err.h new file mode 100644 index 0000000000..a3e8f97825 --- /dev/null +++ b/src/tools/pg_bsd_indent/err.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: stable/11/include/err.h 203964 2010-02-16 19:39:50Z imp $ + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * This is cut down to just the minimum that we need to build indent. + */ + +void err(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); +void errx(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); + +#endif /* !_ERR_H_ */ diff --git a/src/tools/pg_bsd_indent/indent.1 b/src/tools/pg_bsd_indent/indent.1 new file mode 100644 index 0000000000..131abfe70b --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.1 @@ -0,0 +1,618 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)indent.1 8.1 (Berkeley) 7/1/93 +.\" $FreeBSD: head/usr.bin/indent/indent.1 309524 2016-12-04 03:10:25Z pfg $ +.\" +.Dd December 2, 2016 +.Dt INDENT 1 +.Os +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm +.Op Ar input-file Op Ar output-file +.Op Fl bacc | Fl nbacc +.Op Fl bad | Fl nbad +.Op Fl badp | Fl nbadp +.Op Fl bap | Fl nbap +.Op Fl bbb | Fl nbbb +.Op Fl \&bc | Fl nbc +.Op Fl \&bl | Fl \&br +.Op Fl bs | Fl nbs +.Op Fl c Ns Ar n +.Op Fl cp Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Op Fl dj | Fl ndj +.Bk -words +.Op Fl ei | Fl nei +.Op Fl eei | Fl neei +.Ek +.Bk -words +.Op Fl fbs | Fl nfbs +.Op Fl fc1 | Fl nfc1 +.Op Fl fcb | Fl nfcb +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&ldi Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl \&lpl | Fl nlpl +.Op Fl npro +.Op Fl P Ns Ar file +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl sac | Fl nsac +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl \&ta +.Op Fl T Ns Ar typename +.Op Fl tpg | Fl ntpg +.Op Fl ts Ns Ar n +.Op Fl U Ns Ar file +.Op Fl ut | Fl nut +.Op Fl v | Fl \&nv +.Op Fl -version +.Sh DESCRIPTION +The +.Nm +utility is a +.Em C +program formatter. +It reformats the +.Em C +program in the +.Ar input-file +according to the switches. +The switches which can be +specified are described below. +They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input-file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input-file +and a backup copy of +.Ar input-file +is written in the current directory. +If +.Ar input-file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Sq Pa file.BAK . +.Pp +If +.Ar output-file +is specified, +.Nm +checks to make sure that it is different from +.Ar input-file . +.Pp +The options listed below control the formatting style imposed by +.Nm . +.Bl -tag -width Op +.It Fl bacc , nbacc +If +.Fl bacc +is specified, a blank line is forced around every conditional +compilation block. +For example, in front of every #ifdef and after every #endif. +Other blank lines surrounding such blocks will be swallowed. +Default: +.Fl nbacc . +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. +Default: +.Fl nbad . +.It Fl badp , nbadp +This is vaguely similar to +.Fl bad +except that it only applies to the first set of declarations +in a procedure (just after the first `{') and it causes a blank +line to be generated even if there are no declarations. +The default is +.Fl nbadp. +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. +Default: +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. +Default: +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. +Default: +.Fl \&nbc . +.It Fl \&bl , \&br +Specifying +.Fl \&bl +lines up compound statements like this: +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.It Fl bs , nbs +Whether a blank should always be inserted after sizeof. +The default is +.Fl nbs. +.It Fl c Ns Ar n +The column in which comments on code start. +The default is 33. +.It Fl cp Ns Ar n +The column in which comments on #else and #endif start. +The default is 0, which effectively separates the directives from comments by +a single space. +.It Fl cd Ns Ar n +The column in which comments on declarations start. +The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. +With +this option enabled, comments look like this: +.Bd -literal -offset indent + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. +The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing of `else's to cuddle up to the immediately preceding +`}'. +The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. +Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect +or the continuation indent is exactly half of the main indent. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0.5 +causes case labels to be indented half a tab stop. +The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. +For example, +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. +Specifying the default +.Fl \&d\&0 +lines up these comments with the code. +See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, +of global variable names and all struct/union member names +relative to the beginning of their type declaration. +The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. +The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. +If it is enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +The default is +.Fl ei . +.It Fl eei , neei +Enables (disables) extra indentation on continuation lines of +the expression part of +.Ic if +and +.Ic while +statements. +These continuation lines will be indented one extra level. +The default is +.Fl neei . +.It Fl fbs , nfbs +Enables (disables) splitting the function declaration and opening brace +across two lines. +The default is +.Fl fbs . +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. +In such cases, +.Fl nfc1 +should be +used. +The default is +.Fl fc1 . +.It Fl fcb , nfcb +Enables (disables) the formatting of block comments (ones that begin +with `/*\\n'). +Often, block comments have been not so carefully hand formatted by the +programmer, but reformatting that would just change the line breaks is not +wanted. +In such cases, +.Fl nfcb +should be used. +Block comments are then handled like box comments. +The default is +.Fl fcb . +.It Fl i Ns Ar n +The number of columns for one indentation level. +The default is 8. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. +The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. +The default is 78. +.It Fl lc Ns Ar n +Maximum length of an output line in a block comment. +The default is 0, which means to limit block comment lines in accordance with +.Fl l. +.It Fl \&ldi Ns Ar n +Specifies the indentation, in character positions, +of local variable names +relative to the beginning of their type declaration. +The default is for local variable names to be indented +by the same amount as global ones. +.It Fl \&lp , nlp +Lines up code surrounded by parentheses in continuation lines. +With +.Fl \&lp , +if a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. +For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.Bd -literal -offset indent +p1 = first_procedure(second_procedure(p2, p3), +\ \ third_procedure(p4, p5)); +.Ed +.Pp +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2,\ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5)); +.Ed +.Pp +Inserting two more newlines we get: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl \&lpl , nlpl +With +.Fl \&lpl , +code surrounded by parentheses in continuation lines is lined up even if it +would extend past the right margin. +With +.Fl \&nlpl +(the default), such a line that would extend past the right margin is moved +left to keep it within the margin, if that does not require placing it to +the left of the prevailing indentation level. +These switches have no effect if +.Fl nlp +is selected. +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl P Ns Ar file +Read profile from +.Ar file . +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. +The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. +The +default is +.Fl psl . +.It Fl sac , nsac +Control whether parenthesized type names in casts are followed by a space or +not. +The default is +.Fl nsac . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +The default is +.Fl sc . +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. +You can use this to +get rid of blank lines after declarations. +Default: +.Fl nsob . +.It Fl \&st +Causes +.Nm +to take its input from stdin and put its output to stdout. +.It Fl ta +Automatically add all identifiers ending in "_t" to the list +of type keywords. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. +Names accumulate: +.Fl T +can be specified more than once. +You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program will not be formatted as nicely as +it should. +This sounds like a painful thing to have to do, but it is really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm +cannot find all +instances of +.Ic typedef . +.It Fl tpg , ntpg +If +.Fl tpg +is specified, follow Postgres rules about when to use spaces versus +tabs for indentation, that is, use a space instead of a tab if the +tab would move only one column and no tab will follow it. +Default: +.Fl ntpg . +.It Fl ts Ns Ar n +Assumed distance between tab stops. +The default is 8. +.It Fl U Ns Ar file +Adds type names from +.Ar file +to the list of type keywords. +.It Fl ut , nut +Enables (disables) the use of tab characters in the output. +The default is +.Fl ut . +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. +When in verbose mode, +.Nm +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. +The default is +.Fl \&nv . +.It Fl -version +Causes +.Nm +to print its version number and exit. +.El +.Pp +You may set up your own `profile' of defaults to +.Nm +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. +A `.indent.pro' in the current directory takes +precedence over the one in your login directory. +If +.Nm +is run and a profile file exists, then it is read to set up the program's +defaults. +Switches on the command line, though, always override profile +switches. +The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +The +.Nm +utility +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +The +.Nm +utility fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. +Blank lines break paragraphs. +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. +Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. +If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Ss Preprocessor lines +In general, +.Nm +leaves preprocessor lines alone. +The only +reformatting that it will do is to straighten up trailing comments. +It +leaves embedded comments alone. +Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Ss C syntax +The +.Nm +utility understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. +It attempts to cope with the usual sorts of +incomplete and malformed syntax. +In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +The +.Nm +utility uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +The +.Nm +utility has even more switches than +.Xr ls 1 . +.Pp +A common mistake is to try to indent all the +.Em C +programs in a directory by typing: +.Pp +.Dl indent *.c +.Pp +This is probably a bug, not a feature. diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c new file mode 100644 index 0000000000..d3a0ecefe9 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.c @@ -0,0 +1,1279 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <sys/param.h> +#include <err.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +/* Tell indent_globs.h to define our global variables here */ +#define DECLARE_INDENT_GLOBALS 1 + +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void bakcopy(void); +static void indent_declaration(int, int); + +const char *in_name = "Standard Input"; /* will always point to name of input + * file */ +const char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +int +main(int argc, char **argv) +{ + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int force_nl; /* when true, code must be broken */ + int hd_type = 0; /* used to store type of stmt for if (...), + * for (...), etc */ + int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expression of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a <c>?<s>:<s> + * construct */ + const char *t_ptr; /* used for copying tokens */ + int tabs_to_var; /* true if using tabs to indent to var name */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + const char *profile_name = NULL; + struct parser_state transient_state; /* a copy for lookup */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + found_err = 0; + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + if (combuf == NULL) + err(1, NULL); + labbuf = (char *) malloc(bufsize); + if (labbuf == NULL) + err(1, NULL); + codebuf = (char *) malloc(bufsize); + if (codebuf == NULL) + err(1, NULL); + tokenbuf = (char *) malloc(bufsize); + if (tokenbuf == NULL) + err(1, NULL); + alloc_typenames(); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + if (in_buffer == NULL) + err(1, NULL); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + scase = ps.pcase = false; + squest = 0; + sc_end = NULL; + bp_save = NULL; + be_save = NULL; + + output = NULL; + tabs_to_var = 0; + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + lineup_to_parens_always = 0; /* -nlpl */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.local_decl_indent = -1; /* if this is not set to some nonnegative value + * by an arg, we will set this equal to + * ps.decl_ind */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_block_comments = 1; /* -fcb */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0') + profile_name = argv[i]; /* non-empty -P (set profile) */ + set_defaults(); + if (i >= argc) + set_profile(profile_name); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == NULL) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == NULL) /* check for open error */ + err(1, "%s", in_name); + continue; + } + else if (output == NULL) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + errx(1, "input and output files must be different"); + } + output = fopen(out_name, "w"); + if (output == NULL) /* check for create error */ + err(1, "%s", out_name); + continue; + } + errx(1, "unknown parameter: %s", argv[i]); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == NULL) + input = stdin; + if (output == NULL) { + if (input == stdin) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + } + + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.local_decl_indent < 0) /* if not specified by user, set this */ + ps.local_decl_indent = ps.decl_indent; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + char *p = buf_ptr; + int col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = tabsize * (1 + (col - 1) / tabsize) + 1; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int comment_buffered = false; + + type_code = lexi(&ps); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + + /* + * The following code moves newlines and comments following an if (), + * while (), else, etc. up to the start of the following stmt to + * a buffer. This allows proper handling of both kinds of brace + * placement (-br, -bl) and cuddling "else" (-ce). + */ + + while (ps.search_brace) { + switch (type_code) { + case newline: + if (sc_end == NULL) { + save_com = sc_buf; + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + *sc_end++ = '\n'; + /* + * We may have inherited a force_nl == true from the previous + * token (like a semicolon). But once we know that a newline + * has been scanned in this loop, force_nl should be false. + * + * However, the force_nl == true must be preserved if newline + * is never scanned in this loop, so this assignment cannot be + * done earlier. + */ + force_nl = false; + case form_feed: + break; + case comment: + if (sc_end == NULL) { + /* + * Copy everything from the start of the line, because + * pr_comment() will use that to calculate original + * indentation of a boxed comment. + */ + memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4); + save_com = sc_buf + (buf_ptr - in_buffer - 4); + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + comment_buffered = true; + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + if (sc_end >= &save_com[sc_size]) { /* check for temp buffer + * overflow */ + diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + case lbrace: + /* + * Put KNF-style lbraces before the buffered up tokens and + * jump out of this loop in order to avoid copying the token + * again under the default case of the switch below. + */ + if (sc_end != NULL && btype_2) { + save_com[0] = '{'; + /* + * Originally the lbrace may have been alone on its own + * line, but it will be moved into "the else's line", so + * if there was a newline resulting from the "{" before, + * it must be scanned now and ignored. + */ + while (isspace((unsigned char)*buf_ptr)) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '\n') + break; + } + goto sw_buffer; + } + /* FALLTHROUGH */ + default: /* it is the start of a normal statement */ + { + int remove_newlines; + + remove_newlines = + /* "} else" */ + (type_code == sp_nparen && *token == 'e' && + e_code != s_code && e_code[-1] == '}') + /* "else if" */ + || (type_code == sp_paren && *token == 'i' && + last_else && ps.else_if); + if (remove_newlines) + force_nl = false; + if (sc_end == NULL) { /* ignore buffering if + * comment wasn't saved up */ + ps.search_brace = false; + goto check_type; + } + while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) { + sc_end--; + } + if (swallow_optional_blanklines || + (!comment_buffered && remove_newlines)) { + force_nl = !remove_newlines; + while (sc_end > save_com && sc_end[-1] == '\n') { + sc_end--; + } + } + if (force_nl) { /* if we should insert a nl here, put + * it into the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the + * newline is read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose) /* print error msg if the line was + * not already broken */ + diag2(0, "Line broken"); + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + break; + } + } /* end of switch */ + /* + * We must make this check, just in case there was an unexpected + * EOF. + */ + if (type_code != 0) { + /* + * The only intended purpose of calling lexi() below is to + * categorize the next token in order to decide whether to + * continue buffering forthcoming tokens. Once the buffering + * is over, lexi() will be called again elsewhere on all of + * the tokens - this time for normal processing. + * + * Calling it for this purpose is a bug, because lexi() also + * changes the parser state and discards leading whitespace, + * which is needed mostly for comment-related considerations. + * + * Work around the former problem by giving lexi() a copy of + * the current parser state and discard it if the call turned + * out to be just a look ahead. + * + * Work around the latter problem by copying all whitespace + * characters into the buffer so that the later lexi() call + * will read them. + */ + if (sc_end != NULL) { + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + *sc_end++ = *buf_ptr++; + if (sc_end >= &save_com[sc_size]) { + errx(1, "input too long"); + } + } + if (buf_ptr >= buf_end) { + fill_buffer(); + } + } + transient_state = ps; + type_code = lexi(&transient_state); /* read another token */ + if (type_code != newline && type_code != form_feed && + type_code != comment && !transient_state.search_brace) { + ps = transient_state; + } + } + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag2(1, "Stuff missing from end of file"); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + int len = e_com - s_com; + + CHECK_SIZE_CODE(len + 3); + *e_code++ = ' '; + memcpy(e_code, s_com, len); + e_code += len; + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE(3); /* maximum number of increments of e_code + * before the next CHECK_SIZE_CODE or + * dump_line() is 2. After that there's the + * final increment for the null character. */ + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + /* count parens to make Healy happy */ + if (++ps.p_l_follow == nitems(ps.paren_indents)) { + diag3(0, "Reached internal limit of %d unclosed parens", + nitems(ps.paren_indents)); + ps.p_l_follow--; + } + if (*token == '[') + /* not a function pointer declaration or a function call */; + else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* function pointer declarations */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank && + ((ps.last_token != ident && ps.last_token != funcname) || + /* offsetof (1) is never allowed a space; sizeof (2) gets + * one iff -bs; all other keywords (>2) always get a space + * before lparen */ + ps.keyword + Bill_Shannon > 2)) + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + /* + * parenthesized type following sizeof or offsetof is not a cast, + * and we assume the same for any other non-keyword identifier, + * to support macros that take types + */ + if (ps.last_token == ident && + (ps.keyword == 0 || ps.keyword == 1 || ps.keyword == 2)) + ps.not_cast_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + ps.want_blank = space_after_cast; + } else + ps.want_blank = true; + ps.not_cast_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag3(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* pointer declarations */ + + /* + * if this is a unary op in a declaration, we should indent + * this token + */ + for (i = 0; token[i]; ++i) + /* find length of token */; + indent_declaration(dec_ind - i, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank) + *e_code++ = ' '; + + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len); + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * <c>?<n>:<n> construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_or_st) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + /* + * turn everything so far into a label + */ + { + int len = e_code - s_code; + + CHECK_SIZE_LAB(len + 3); + memcpy(e_lab, s_code, len); + e_lab += len; + *e_lab++ = ':'; + *e_lab = '\0'; + e_code = s_code; + } + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + if (ps.dec_nest == 0) + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in an error */ + squest = 0; + if (ps.last_token == rparen) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.not_cast_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent stray semicolons in declarations */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for an if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after an end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + if (function_brace_split) { /* dump the line prior to the + * brace ... */ + dump_line(); + ps.want_blank = false; + } else /* add a space between the decl and brace */ + ps.want_blank = true; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceding unbalanced + * parens */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest] = dec_ind; + if (++ps.dec_nest == nitems(di_stack)) { + diag3(0, "Reached internal limit of %d struct levels", + nitems(di_stack)); + ps.dec_nest--; + } + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we can't be in the middle of + * a declaration, so don't do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + ps.in_decl = false; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag2(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case type_def: + case storage: + prefix_blankline_requested = 0; + goto copy_id; + + case structure: + if (ps.p_l_follow > 0) + goto copy_id; + /* FALLTHROUGH */ + case decl: /* we have a declaration type (int, etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + if (ps.ind_level == 0 || ps.dec_nest > 0) { + /* global variable or struct member in local variable */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); + } else { + /* local variable */ + dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; + tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); + } + goto copy_id; + + case funcname: + case ident: /* got an identifier or constant */ + if (ps.in_decl) { + if (type_code == funcname) { + ps.in_decl = false; + if (procnames_start_line && s_code != e_code) { + *e_code = '\0'; + dump_line(); + } + else if (ps.want_blank) { + *e_code++ = ' '; + } + ps.want_blank = false; + } + else if (!ps.block_init && !ps.dumped_decl_indent && + ps.paren_level == 0) { /* if we are in a declaration, we + * must indent identifier */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + ps.want_blank = false; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, s_token, len); + e_code += len; + } + if (type_code != funcname) + ps.want_blank = true; + break; + + case strpfx: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent leading commas and not the actual identifiers */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || + count_spaces_until(compute_code_target(), s_code, e_code) > + max_col - tabsize)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + CHECK_SIZE_LAB(1); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || (in_comment && !had_eof)) { + CHECK_SIZE_LAB(2); + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == NULL) { + /* comment on preprocessor line */ + if (sc_end == NULL) { /* if this is the first comment, + * we must set up the buffer */ + save_com = sc_buf; + sc_end = &save_com[0]; + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + if (sc_end - save_com + com_end - com_start > sc_size) + errx(1, "input too long"); + memmove(sc_end, s_lab + com_start, com_end - com_start); + sc_end += com_end - com_start; + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + } + CHECK_SIZE_LAB(1); + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */ + if ((size_t)ifdef_level < nitems(state_stack)) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag2(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */ + if (ifdef_level <= 0) + diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag2(1, "Unmatched #endif"); + else + ifdef_level--; + } else { + struct directives { + int size; + const char *string; + } + recognized[] = { + {7, "include"}, + {6, "define"}, + {5, "undef"}, + {4, "line"}, + {5, "error"}, + {6, "pragma"} + }; + int d = nitems(recognized); + while (--d >= 0) + if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0) + break; + if (d < 0) { + diag2(1, "Unrecognized cpp directive"); + break; + } + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + else { + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a / followed by * this is a biggie */ + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +static void +bakcopy(void) +{ + int n, + bakchn; + char buff[8 * 1024]; + const char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(1, "%s", bakfile); + while ((n = read(fileno(input), buff, sizeof(buff))) > 0) + if (write(bakchn, buff, n) != n) + err(1, "%s", bakfile); + if (n < 0) + err(1, "%s", in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == NULL) + err(1, "%s", bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == NULL) { + unlink(bakfile); + err(1, "%s", in_name); + } +} + +static void +indent_declaration(int cur_dec_ind, int tabs_to_var) +{ + int pos = e_code - s_code; + char *startpos = e_code; + + /* + * get the tab math right for indentations that are not multiples of tabsize + */ + if ((ps.ind_level * ps.ind_size) % tabsize != 0) { + pos += (ps.ind_level * ps.ind_size) % tabsize; + cur_dec_ind += (ps.ind_level * ps.ind_size) % tabsize; + } + if (tabs_to_var) { + int tpos; + + CHECK_SIZE_CODE(cur_dec_ind / tabsize); + while ((tpos = tabsize * (1 + pos / tabsize)) <= cur_dec_ind) { + *e_code++ = (!postgres_tab_rules || + tpos != pos + 1 || + cur_dec_ind >= tpos + tabsize) ? '\t' : ' '; + pos = tpos; + } + } + CHECK_SIZE_CODE(cur_dec_ind - pos + 1); + while (pos < cur_dec_ind) { + *e_code++ = ' '; + pos++; + } + if (e_code == startpos && ps.want_blank) { + *e_code++ = ' '; + ps.want_blank = false; + } +} diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h new file mode 100644 index 0000000000..1708dbc19f --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2001 Jens Schweikhardt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); +#endif + +#define nitems(array) (sizeof (array) / sizeof (array[0])) + +void add_typename(const char *); +void alloc_typenames(void); +int compute_code_target(void); +int compute_label_target(void); +int count_spaces(int, char *); +int count_spaces_until(int, char *, char *); +int lexi(struct parser_state *); +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); +void set_defaults(void); +void set_option(char *); +void set_profile(const char *); diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h new file mode 100644 index 0000000000..24c43fa420 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_codes.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_codes.h 309380 2016-12-02 01:25:51Z pfg $ + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 +#define strpfx 33 +#define storage 34 +#define funcname 35 +#define type_def 36 +#define structure 37 diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h new file mode 100644 index 0000000000..398784b3f4 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -0,0 +1,343 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_globs.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_globs.h 303735 2016-08-03 22:08:07Z pfg $ + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + + +#ifndef false +#define false 0 +#endif +#ifndef true +#define true 1 +#endif + +/* + * Exactly one calling file should define this symbol. The global variables + * will be defined in that file, and just referenced elsewhere. + */ +#ifdef DECLARE_INDENT_GLOBALS +#define extern +#endif + +extern FILE *input; /* the fid for the input file */ +extern FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE(desired_size) \ + if (e_code + (desired_size) >= l_code) { \ + int nsize = l_code-s_code + 400 + desired_size; \ + int code_len = e_code-s_code; \ + codebuf = (char *) realloc(codebuf, nsize); \ + if (codebuf == NULL) \ + err(1, NULL); \ + e_code = codebuf + code_len + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM(desired_size) \ + if (e_com + (desired_size) >= l_com) { \ + int nsize = l_com-s_com + 400 + desired_size; \ + int com_len = e_com - s_com; \ + int blank_pos; \ + if (last_bl != NULL) \ + blank_pos = last_bl - combuf; \ + else \ + blank_pos = -1; \ + combuf = (char *) realloc(combuf, nsize); \ + if (combuf == NULL) \ + err(1, NULL); \ + e_com = combuf + com_len + 1; \ + if (blank_pos > 0) \ + last_bl = combuf + blank_pos; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB(desired_size) \ + if (e_lab + (desired_size) >= l_lab) { \ + int nsize = l_lab-s_lab + 400 + desired_size; \ + int label_len = e_lab - s_lab; \ + labbuf = (char *) realloc(labbuf, nsize); \ + if (labbuf == NULL) \ + err(1, NULL); \ + e_lab = labbuf + label_len + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN(desired_size) \ + if (e_token + (desired_size) >= l_token) { \ + int nsize = l_token-s_token + 400 + desired_size; \ + int token_len = e_token - s_token; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + if (tokenbuf == NULL) \ + err(1, NULL); \ + e_token = tokenbuf + token_len + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +extern char *labbuf; /* buffer for label */ +extern char *s_lab; /* start ... */ +extern char *e_lab; /* .. and end of stored label */ +extern char *l_lab; /* limit of label buffer */ + +extern char *codebuf; /* buffer for code section */ +extern char *s_code; /* start ... */ +extern char *e_code; /* .. and end of stored code */ +extern char *l_code; /* limit of code section */ + +extern char *combuf; /* buffer for comments */ +extern char *s_com; /* start ... */ +extern char *e_com; /* ... and end of stored comments */ +extern char *l_com; /* limit of comment buffer */ + +#define token s_token +extern char *tokenbuf; /* the last token scanned */ +extern char *s_token; +extern char *e_token; +extern char *l_token; + +extern char *in_buffer; /* input buffer */ +extern char *in_buffer_limit; /* the end of the input buffer */ +extern char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +extern char *buf_end; /* ptr to first after last char in in_buffer */ + +extern char sc_buf[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +extern char *save_com; /* start of the comment stored in sc_buf */ +extern char *sc_end; /* pointer into save_com buffer */ + +extern char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +extern char *be_save; /* similarly saved value of buf_end */ + + +extern int found_err; +extern int blanklines_after_declarations; +extern int blanklines_before_blockcomments; +extern int blanklines_after_procs; +extern int blanklines_around_conditional_compilation; +extern int swallow_optional_blanklines; +extern int n_real_blanklines; +extern int prefix_blankline_requested; +extern int postfix_blankline_requested; +extern int break_comma; /* when true and not in parens, break after a + * comma */ +extern int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +extern float case_ind; /* indentation level to be used for a "case + * n:" */ +extern int code_lines; /* count of lines with code */ +extern int had_eof; /* set to true when input is exhausted */ +extern int line_no; /* the current line number. */ +extern int max_col; /* the maximum allowable line length */ +extern int verbose; /* when true, non-essential error messages are + * printed */ +extern int cuddle_else; /* true if else should cuddle up to '}' */ +extern int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +extern int comment_delimiter_on_blankline; +extern int troff; /* true iff were generating troff input */ +extern int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +extern int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +extern int format_block_comments; /* true if comments beginning with + * `/ * \n' are to be reformatted */ +extern int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +extern int inhibit_formatting; /* true if INDENT OFF is in effect */ +extern int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +extern int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +extern int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +extern int lineup_to_parens_always; /* if true, do not attempt to keep + * lined-up code within the margin */ +extern int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +extern int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +extern int block_comment_max_col; +extern int extra_expression_indent; /* true if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ +extern int function_brace_split; /* split function declaration and + * brace onto separate lines */ +extern int use_tabs; /* set true to use tabs for spacing, + * false uses all spaces */ +extern int auto_typedefs; /* set true to recognize identifiers + * ending in "_t" like typedefs */ +extern int space_after_cast; /* "b = (int) a" vs "b = (int)a" */ +extern int postgres_tab_rules; /* use Postgres tab-vs-space rules */ +extern int tabsize; /* the size of a tab */ +extern int else_endif_com_ind; /* the column in which comments to + * the right of #else and #endif + * should start */ + +extern int ifdef_level; + +struct parser_state { + int last_token; + int p_stack[256]; /* this is the parsers stack */ + int il[64]; /* this stack stores indentation levels */ + float cstk[32]; /* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in / followed by * */ + int comment_delta; /* used to set up indentation for all lines + * of a boxed comment after the first one */ + int n_comment_delta;/* remembers how many columns there were + * before the start of a box comment so that + * forthcoming lines of the comment are + * indented properly */ + int cast_mask; /* indicates which close parens potentially + * close off casts */ + int not_cast_mask; /* indicates which close parens definitely + * close off something else than casts */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * comment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within statements */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int local_decl_indent; /* like decl_indent but for locals */ + int keyword; /* the type of a keyword or 0 */ + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +}; + +extern struct parser_state ps; +extern struct parser_state state_stack[5]; +extern struct parser_state match_state[5]; + +/* Undo previous hackery */ +#ifdef DECLARE_INDENT_GLOBALS +#undef extern +#endif diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c new file mode 100644 index 0000000000..3ce8bfb70c --- /dev/null +++ b/src/tools/pg_bsd_indent/io.c @@ -0,0 +1,608 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +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 +dump_line(void) +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + int cur_col, + target_col = 1; + static int not_first_line; + + if (ps.procname[0]) { + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) { + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + *e_lab = '\0'; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + (int)(e_lab - s), s); + } + else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + int i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) { /* print comment, if any */ + int target = ps.com_col; + char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') /* consider original indentation in + * case this is a box comment */ + com_st++, target += tabsize; + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = tabsize * (1 + (target - 1) / tabsize) + 1, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment can't fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace((unsigned char)e_com[-1])) + e_com--; + (void)pad_output(cur_col, target); + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com = combuf + 1) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + if (ps.paren_level > 0) + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; +} + +int +compute_code_target(void) +{ + int target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent + * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level); + else if (lineup_to_parens_always) + target_col = paren_target; + else { + int w; + int t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int +compute_label_target(void) +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : 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 + * + * All rights reserved + * + * + * NAME: fill_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 + * buffer from temporary buffer + * + */ +void +fill_buffer(void) +{ /* this routine reads stuff from the input */ + char *p; + int i; + FILE *f = input; + + if (bp_save != NULL) { /* there is a partly filled input buffer left */ + 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 */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + int size = (in_buffer_limit - in_buffer) * 2 + 10; + int offset = p - in_buffer; + in_buffer = realloc(in_buffer, size); + if (in_buffer == NULL) + errx(1, "input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + 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; + } + buf_ptr = in_buffer; + buf_end = p; + if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') { + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + } + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column + * target integer The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +static int +pad_output(int current, int target) + /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + /* current: the current column value */ + /* target: position we want it at */ +{ + int curr; /* internal column pointer */ + + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + if (use_tabs) { + int tcur; + + while ((tcur = tabsize * (1 + (curr - 1) / tabsize) + 1) <= target) { + putc((!postgres_tab_rules || + tcur != curr + 1 || + target >= tcur + tabsize) ? '\t' : ' ', output); + curr = tcur; + } + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces_until(int cur, char *buffer, char *end) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ +{ + char *buf; /* used to look thru buffer */ + + for (buf = buffer; *buf != '\0' && buf != end; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = tabsize * (1 + (cur - 1) / tabsize) + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +int +count_spaces(int cur, char *buffer) +{ + return (count_spaces_until(cur, buffer, NULL)); +} + +void +diag4(int level, const char *msg, int a, int b) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void +diag3(int level, const char *msg, int a) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a); + fprintf(stderr, "\n"); + } +} + +void +diag2(int level, const char *msg) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, "%s", msg); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, "%s", msg); + fprintf(stderr, "\n"); + } +} + diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c new file mode 100644 index 0000000000..f01596a870 --- /dev/null +++ b/src/tools/pg_bsd_indent/lexi.c @@ -0,0 +1,724 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include <err.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +#define alphanum 1 +#ifdef undef +#define opchar 3 +#endif + +struct templ { + const char *rwd; + int rwcode; +}; + +/* + * This table has to be sorted alphabetically, because it'll be used in binary + * search. For the same reason, string must be the first thing in struct templ. + */ +struct templ specials[] = +{ + {"_Bool", 4}, + {"_Complex", 4}, + {"_Imaginary", 4}, + {"auto", 10}, + {"bool", 4}, + {"break", 9}, + {"case", 8}, + {"char", 4}, + {"complex", 4}, + {"const", 4}, + {"continue", 12}, + {"default", 8}, + {"do", 6}, + {"double", 4}, + {"else", 6}, + {"enum", 3}, + {"extern", 10}, + {"float", 4}, + {"for", 5}, + {"global", 4}, + {"goto", 9}, + {"if", 5}, + {"imaginary", 4}, + {"inline", 12}, + {"int", 4}, + {"long", 4}, + {"offsetof", 1}, + {"register", 10}, + {"restrict", 12}, + {"return", 9}, + {"short", 4}, + {"signed", 4}, + {"sizeof", 2}, + {"static", 10}, + {"struct", 3}, + {"switch", 7}, + {"typedef", 11}, + {"union", 3}, + {"unsigned", 4}, + {"void", 4}, + {"volatile", 4}, + {"while", 5} +}; + +const char **typenames; +int typename_count; +int typename_top = -1; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + +static int +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) +{ + int unary_delim; /* this is set to 1 if the current token + * forces a following operator to be unary */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + state->col_1 = state->last_nl; /* tell world that this token started + * in column 1 iff the last thing + * scanned was a newline */ + state->last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + state->col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr & 127] == alphanum || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + /* + * we have a character or number + */ + struct templ *p; + + if (isdigit((unsigned char)*buf_ptr) || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + int seendot = 0, + seenexp = 0, + seensfx = 0; + + /* + * base 2, base 8, base 16: + */ + if (buf_ptr[0] == '0' && buf_ptr[1] != '.') { + int len; + + if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B') + len = strspn(buf_ptr + 2, "01") + 2; + else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X') + len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2; + else + len = strspn(buf_ptr + 1, "012345678") + 1; + if (len > 0) { + CHECK_SIZE_TOKEN(len); + memcpy(e_token, buf_ptr, len); + e_token += len; + buf_ptr += len; + } + else + diag2(1, "Unterminated literal"); + } + else /* base 10: */ + while (1) { + if (*buf_ptr == '.') { + if (seendot) + break; + else + seendot++; + } + CHECK_SIZE_TOKEN(3); + *e_token++ = *buf_ptr++; + if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') { + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + } + + while (1) { + CHECK_SIZE_TOKEN(2); + if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) { + *e_token++ = *buf_ptr++; + seensfx |= 1; + continue; + } + if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) { + if (buf_ptr[1] == buf_ptr[0]) + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + seensfx |= 2; + continue; + } + break; + } + } + else + while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) { + /* fill_buffer() terminates buffer with newline */ + if (*buf_ptr == BACKSLASH) { + if (*(buf_ptr + 1) == '\n') { + buf_ptr += 2; + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; + } + CHECK_SIZE_TOKEN(1); + /* copy it over */ + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token = '\0'; + + if (s_token[0] == 'L' && s_token[1] == '\0' && + (*buf_ptr == '"' || *buf_ptr == '\'')) + return (strpfx); + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + state->keyword = 0; + if (state->last_token == structure && !state->p_l_follow) { + /* if last token was 'struct' and we're not + * in parentheses, then this token + * should be treated as a declaration */ + state->last_u_d = true; + return (decl); + } + /* + * Operator after identifier is binary unless last token was 'struct' + */ + state->last_u_d = (state->last_token == structure); + + p = bsearch(s_token, + specials, + sizeof(specials) / sizeof(specials[0]), + sizeof(specials[0]), + strcmp_type); + if (p == NULL) { /* not a special keyword... */ + char *u; + + /* ... so maybe a type_t or a typedef */ + if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) && + strcmp(u, "_t") == 0) || (typename_top >= 0 && + bsearch(s_token, typenames, typename_top + 1, + sizeof(typenames[0]), strcmp_type))) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + goto found_typename; + } + } else { /* we have a keyword */ + state->keyword = p->rwcode; + state->last_u_d = true; + switch (p->rwcode) { + case 7: /* it is a switch */ + return (swstmt); + case 8: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + /* FALLTHROUGH */ + case 4: /* one of the declaration keywords */ + found_typename: + if (state->p_l_follow) { + /* inside parens: cast, param list, offsetof or sizeof */ + state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask; + } + if (state->last_token == period || state->last_token == unary_op) { + state->keyword = 0; + break; + } + if (p != NULL && p->rwcode == 3) + return (structure); + if (state->p_l_follow) + break; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 10: /* storage class specifier */ + return (storage); + + case 11: /* typedef */ + return (type_def); + + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 && + state->in_parameter_declaration == 0 && state->block_init == 0) { + 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 + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + else if (!state->p_l_follow && !state->block_init && + !state->in_stmt && + ((*buf_ptr == '*' && buf_ptr[1] != '=') || + isalpha((unsigned char)*buf_ptr)) && + (state->last_token == semicolon || state->last_token == lbrace || + state->last_token == rbrace)) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + return decl; + } + if (state->last_token == decl) /* if this is a declared variable, + * then following sign is unary */ + state->last_u_d = true; /* will make "int a -1" work */ + return (ident); /* the ident is not in the list */ + } /* end of processing for alphanum character */ + + /* Scan a non-alphanumeric token */ + + CHECK_SIZE_TOKEN(3); /* things like "<<=" */ + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = state->last_u_d; + state->last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exhausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + do { /* copy the string */ + while (1) { /* move one character or [/<char>]<char> */ + if (*buf_ptr == '\n') { + diag2(1, "Unterminated literal"); + goto stop_lit; + } + CHECK_SIZE_TOKEN(2); + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = state->last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (state->in_or_st) state->block_init = 1; + */ + /* ? code = state->block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = state->block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = state->last_u_d; + state->last_nl = true; /* remember this so we can set 'state->col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (state->last_token == ident || state->last_token == rparen) { + code = (state->last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + unary_delim = false; + code = unary_op; + state->want_blank = false; + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (state->in_or_st) + state->block_init = 1; +#ifdef undef + if (chartype[*buf_ptr & 127] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + case '*': + unary_delim = true; + if (!state->last_u_d) { + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = binary_op; + break; + } + while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) { + if (*buf_ptr == '*') { + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + } + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = unary_op; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = state->last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + state->last_u_d = unary_delim; + CHECK_SIZE_TOKEN(1); + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +void +alloc_typenames(void) +{ + + typenames = (const char **)malloc(sizeof(typenames[0]) * + (typename_count = 16)); + if (typenames == NULL) + err(1, NULL); +} + +void +add_typename(const char *key) +{ + int comparison; + const char *copy; + + if (typename_top + 1 >= typename_count) { + typenames = realloc((void *)typenames, + sizeof(typenames[0]) * (typename_count *= 2)); + if (typenames == NULL) + err(1, NULL); + } + if (typename_top == -1) + typenames[++typename_top] = copy = strdup(key); + else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) { + /* take advantage of sorted input */ + if (comparison == 0) /* remove duplicates */ + return; + typenames[++typename_top] = copy = strdup(key); + } + else { + int p; + + for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++) + /* find place for the new key */; + if (comparison == 0) /* remove duplicates */ + return; + memmove(&typenames[p + 1], &typenames[p], + sizeof(typenames[0]) * (++typename_top - p)); + typenames[p] = copy = strdup(key); + } + + if (copy == NULL) + err(1, NULL); +} diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c new file mode 100644 index 0000000000..bf6b1697f9 --- /dev/null +++ b/src/tools/pg_bsd_indent/parse.c @@ -0,0 +1,342 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void reduce(void); + +void +parse(int tk) /* tk: the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + /* + * Note that the stack pointer here is decremented, effectively + * reducing "else if" to "if". This saves a lot of stack space + * in case of a long "if-else-if ... else-if" sequence. + */ + ps.i_l_follow = ps.il[ps.tos--]; + /* the rest is the same as for dolit and forstmt */ + /* FALLTHROUGH */ + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag2(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ + if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag2(1, "Statement nesting error"); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag2(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + if (ps.tos >= nitems(ps.p_stack) - 1) + errx(1, "Parser stack overflow"); + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * <stmt> <stmt> <stmtl> + * <stmtl> <stmt> <stmtl> + * do <stmt> "dostmt" + * if <stmt> "ifstmt" + * switch <stmt> <stmt> + * decl <stmt> <stmt> + * "ifelse" <stmt> <stmt> + * for <stmt> <stmt> + * while <stmt> <stmt> + * "dostmt" while <stmt> + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +static void +reduce(void) +{ + int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* <do> <stmt> */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* <if> <stmt> */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* <switch> <stmt> */ + case_ind = ps.cstk[ps.tos - 1]; + /* FALLTHROUGH */ + case decl: /* finish of a declaration */ + case elsehead: + /* <<if> <stmt> else> <stmt> */ + case forstmt: + /* <for> <stmt> */ + case whilestmt: + /* <while> <stmt> */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* <anything else> <stmt> */ + return; + + } /* end of section for <stmt> on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.tos -= 2; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c new file mode 100644 index 0000000000..b0eacac1bb --- /dev/null +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + +void +pr_comment(void) +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = NULL; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + break_delim = false; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*' || + (*buf_ptr == '\n' && !format_block_comments)) { + ps.box_com = true; /* A comment with a '-' or '*' immediately + * after the /+* is assumed to be a boxed + * comment. A comment with a newline + * immediately after the /+* is assumed to + * be a block comment and is treated as a + * box comment unless format_block_comments + * is nonzero (the default). */ + break_delim = false; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + int target_col; + break_delim = false; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + if (s_lab != e_lab && s_lab[1] == 'e' && + (strncmp(s_lab, "#endif", 6) == 0 || + strncmp(s_lab, "#else", 5) == 0)) + ps.com_col = else_endif_com_ind <= target_col + ? target_col + 1 : else_endif_com_ind; + else + ps.com_col = ps.decl_on_line || ps.ind_level == 0 + ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col <= target_col) + ps.com_col = tabsize * (1 + (target_col - 1) / tabsize) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + /* + * Find out how much indentation there was originally, because that + * much will have to be ignored by pad_output() in dump_line(). This + * is a box comment, so nothing changes -- not even indentation. + * + * The comment we're about to read usually comes from in_buffer, + * unless it has been copied into save_com. + */ + char *start; + + start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? + sc_buf : in_buffer; + ps.n_comment_delta = 1 - count_spaces_until(1, start, buf_ptr - 2); + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/' followed by '*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + /* + * Don't put a break delimiter if this is a one-liner that won't wrap. + */ + if (break_delim) + for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) { + if (t_ptr >= buf_end) + fill_buffer(); + if (t_ptr[0] == '*' && t_ptr[1] == '/') { + if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2)) + break_delim = false; + break; + } + } + + if (break_delim) { + char *t = e_com; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments && ps.last_token != lbrace) + prefix_blankline_requested = 1; + dump_line(); + e_com = s_com = t; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + CHECK_SIZE_COM(3); + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = NULL; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t') + ; + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + dump_line(); + return; + } + last_bl = NULL; + CHECK_SIZE_COM(4); + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) + *e_com++ = ' '; + if (!ps.box_com && e_com - s_com > 3) { + dump_line(); + if (star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + else { + ps.last_nl = 1; + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + *e_com++ = ' '; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + CHECK_SIZE_COM(4); + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + if (break_delim) { + if (e_com > s_com + 3) { + dump_line(); + } + else + s_com = e_com; + *e_com++ = ' '; + } + if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com) + *e_com++ = ' '; /* ensure blank before end */ + *e_com++ = '*', *e_com++ = '/', *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else /* handle isolated '*' */ + *e_com++ = '*'; + break; + default: /* we have a random char */ + now_col = count_spaces_until(ps.com_col, s_com, e_com); + do { + CHECK_SIZE_COM(1); + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; /* remember we saw a blank */ + ++e_com; + now_col++; + } while (!memchr("*\n\r\b\t", *buf_ptr, 6) && + (now_col <= adj_max_col || !last_bl)); + ps.last_nl = false; + if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (last_bl == NULL) { + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + break; + } + *e_com = '\0'; + e_com = last_bl; + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t'; + t_ptr++) + ; + last_bl = NULL; + /* + * t_ptr will be somewhere between e_com (dump_line() reset) + * and l_com. So it's safe to copy byte by byte from t_ptr + * to e_com without any CHECK_SIZE_COM(). + */ + while (*t_ptr != '\0') { + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + break; + } + } +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0 b/src/tools/pg_bsd_indent/tests/binary.0 new file mode 100644 index 0000000000..0c5ebf7e8f --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0 @@ -0,0 +1,9 @@ +#define b00101010 -1 +void t(void) { + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0.stdout b/src/tools/pg_bsd_indent/tests/binary.0.stdout new file mode 100644 index 0000000000..6118ac5055 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0.stdout @@ -0,0 +1,11 @@ +#define b00101010 -1 +void +t(void) +{ + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0 b/src/tools/pg_bsd_indent/tests/comments.0 new file mode 100644 index 0000000000..7b65c2eb55 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0 @@ -0,0 +1,52 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void t(void) { + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on the next line. + * + * *test* + */ + + /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */ + + /* r309343 */ +} + +int c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0.stdout b/src/tools/pg_bsd_indent/tests/comments.0.stdout new file mode 100644 index 0000000000..8ca5aa518c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0.stdout @@ -0,0 +1,60 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void +t(void) +{ + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj + * kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on + * the next line. + * + * *test* + */ + + /* + * r309219 Go through linked list, freeing from the malloced (t[-1]) + * address. + */ + + /* r309343 */ +} + +int +c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.pro b/src/tools/pg_bsd_indent/tests/comments.pro new file mode 100644 index 0000000000..0959711b3d --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.pro @@ -0,0 +1 @@ +-bbb \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0 b/src/tools/pg_bsd_indent/tests/cppelsecom.0 new file mode 100644 index 0000000000..79aed65115 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0 @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout new file mode 100644 index 0000000000..047fc3d951 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/declarations.0 b/src/tools/pg_bsd_indent/tests/declarations.0 new file mode 100644 index 0000000000..8419494989 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0 @@ -0,0 +1,79 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct +{ + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex +{ + double x; + double y; +} Complex; + +void +t1 (char *a, int b, + void (*fn)(void)) +{} + +void t2 (char *x, int y) +{ + int a, + b, + c; + int + *d, + *e, + *f; + int (*g)(), + (*h)(), + (*i)(); + int j, + k, + l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int *int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( +struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/declarations.0.stdout b/src/tools/pg_bsd_indent/tests/declarations.0.stdout new file mode 100644 index 0000000000..ab5a447a8b --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0.stdout @@ -0,0 +1,73 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct { + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex { + double x; + double y; +} Complex; + +void +t1(char *a, int b, + void (*fn) (void)) +{ +} + +void +t2(char *x, int y) +{ + int a, b, c; + int + *d, *e, *f; + int (*g) (), (*h) (), (*i) (); + int j, k, l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], + x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int * +int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( + struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0 b/src/tools/pg_bsd_indent/tests/elsecomment.0 new file mode 100644 index 0000000000..61066c22b5 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0 @@ -0,0 +1,42 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void t(void) { + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ int a; else /* b */ int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) { + int a; + } + + + else if (0) { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout new file mode 100644 index 0000000000..7de23be089 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout @@ -0,0 +1,47 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void +t(void) +{ + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) + { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) + { + int a; + } else if (0) + { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.pro b/src/tools/pg_bsd_indent/tests/elsecomment.pro new file mode 100644 index 0000000000..115c4768e7 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.pro @@ -0,0 +1 @@ +-bl \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/enum.0 b/src/tools/pg_bsd_indent/tests/enum.0 new file mode 100644 index 0000000000..15057dc464 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0 @@ -0,0 +1,6 @@ +typedef enum +{ +PREWARM_PREFETCH, /* comment */ +PREWARM_READ, /* more comment */ +PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/enum.0.stdout b/src/tools/pg_bsd_indent/tests/enum.0.stdout new file mode 100644 index 0000000000..fd4653b854 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0.stdout @@ -0,0 +1,5 @@ +typedef enum { + PREWARM_PREFETCH, /* comment */ + PREWARM_READ, /* more comment */ + PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0 b/src/tools/pg_bsd_indent/tests/f_decls.0 new file mode 100644 index 0000000000..aeef03b704 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0 @@ -0,0 +1,27 @@ +char * x(void) +{ + type identifier; + type *pointer; + unused * value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) { + +} + +int +z(void) { + +} + +int x; +int *y; +int * * * * z; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0.stdout b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout new file mode 100644 index 0000000000..bc21248552 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout @@ -0,0 +1,30 @@ +char * +x(void) +{ + type identifier; + type *pointer; + unused *value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) +{ + +} + +int +z(void) +{ + +} + +int x; +int *y; +int ****z; diff --git a/src/tools/pg_bsd_indent/tests/float.0 b/src/tools/pg_bsd_indent/tests/float.0 new file mode 100644 index 0000000000..91f017fc1c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void t(void) { + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/float.0.stdout b/src/tools/pg_bsd_indent/tests/float.0.stdout new file mode 100644 index 0000000000..0f213182ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0.stdout @@ -0,0 +1,8 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void +t(void) +{ + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0 b/src/tools/pg_bsd_indent/tests/label.0 new file mode 100644 index 0000000000..7798a4d5c2 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0 @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void t(void) { + switch (1) + { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0.stdout b/src/tools/pg_bsd_indent/tests/label.0.stdout new file mode 100644 index 0000000000..22ec12272a --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0.stdout @@ -0,0 +1,14 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void +t(void) +{ + switch (1) { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.pro b/src/tools/pg_bsd_indent/tests/label.pro new file mode 100644 index 0000000000..75d1fe1a12 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.pro @@ -0,0 +1 @@ +-nut \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/list_head.0 b/src/tools/pg_bsd_indent/tests/list_head.0 new file mode 100644 index 0000000000..35874ebc4e --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0 @@ -0,0 +1,15 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; + + diff --git a/src/tools/pg_bsd_indent/tests/list_head.0.stdout b/src/tools/pg_bsd_indent/tests/list_head.0.stdout new file mode 100644 index 0000000000..2ebcca5730 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0.stdout @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; diff --git a/src/tools/pg_bsd_indent/tests/nsac.0 b/src/tools/pg_bsd_indent/tests/nsac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.0.stdout b/src/tools/pg_bsd_indent/tests/nsac.0.stdout new file mode 100644 index 0000000000..78f3b28757 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double)8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.pro b/src/tools/pg_bsd_indent/tests/nsac.pro new file mode 100644 index 0000000000..6bcbd2b1ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.pro @@ -0,0 +1 @@ +-nsac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0 b/src/tools/pg_bsd_indent/tests/offsetof.0 new file mode 100644 index 0000000000..078db19c29 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0 @@ -0,0 +1,5 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void t(void) { + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0.stdout b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout new file mode 100644 index 0000000000..199bf0fa07 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout @@ -0,0 +1,7 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void +t(void) +{ + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0 b/src/tools/pg_bsd_indent/tests/parens.0 new file mode 100644 index 0000000000..366536ce82 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0 @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) + { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0.stdout b/src/tools/pg_bsd_indent/tests/parens.0.stdout new file mode 100644 index 0000000000..2258f8d2f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0.stdout @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void +similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.pro b/src/tools/pg_bsd_indent/tests/parens.pro new file mode 100644 index 0000000000..e860911a11 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.pro @@ -0,0 +1 @@ +-ts4 -i4 -di12 -Tallocfunc diff --git a/src/tools/pg_bsd_indent/tests/sac.0 b/src/tools/pg_bsd_indent/tests/sac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.0.stdout b/src/tools/pg_bsd_indent/tests/sac.0.stdout new file mode 100644 index 0000000000..1849b28337 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.pro b/src/tools/pg_bsd_indent/tests/sac.pro new file mode 100644 index 0000000000..2b21505c72 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.pro @@ -0,0 +1 @@ +-sac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/struct.0 b/src/tools/pg_bsd_indent/tests/struct.0 new file mode 100644 index 0000000000..83142bfb19 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0 @@ -0,0 +1,21 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + { D, E }, + { F, G } + }; +} + +void u(struct x a) { + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/struct.0.stdout b/src/tools/pg_bsd_indent/tests/struct.0.stdout new file mode 100644 index 0000000000..3861312865 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0.stdout @@ -0,0 +1,23 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + {D, E}, + {F, G} + }; +} + +void +u(struct x a) +{ + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0 b/src/tools/pg_bsd_indent/tests/surplusbad.0 new file mode 100644 index 0000000000..07d07026db --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0 @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout new file mode 100644 index 0000000000..b288970fb9 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.pro b/src/tools/pg_bsd_indent/tests/surplusbad.pro new file mode 100644 index 0000000000..e828c8191c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.pro @@ -0,0 +1 @@ +-bad \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0 b/src/tools/pg_bsd_indent/tests/types_from_file.0 new file mode 100644 index 0000000000..6efca24fe1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0 @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c *z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout new file mode 100644 index 0000000000..8776ca6ba8 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c * z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.list b/src/tools/pg_bsd_indent/tests/types_from_file.list new file mode 100644 index 0000000000..5f733616b1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.list @@ -0,0 +1,2 @@ +b +a \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.pro b/src/tools/pg_bsd_indent/tests/types_from_file.pro new file mode 100644 index 0000000000..39eb911980 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.pro @@ -0,0 +1 @@ +-Utypes_from_file.list \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/wchar.0 b/src/tools/pg_bsd_indent/tests/wchar.0 new file mode 100644 index 0000000000..9910e77857 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; diff --git a/src/tools/pg_bsd_indent/tests/wchar.0.stdout b/src/tools/pg_bsd_indent/tests/wchar.0.stdout new file mode 100644 index 0000000000..92774abfdd --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; -- 2.31.1 From da770680de94ba589cb29310f42f71c2373e81cf Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 14:08:57 -0500 Subject: [PATCH v3 2/3] Sync pg_bsd_indent's copyright notices with Postgres practice. To avoid confusion, make the copyright notices in these files match the 3-clause form of the BSD license, per the blanket policy update that UC Berkeley issued years ago. Discussion: https://postgr.es/m/20230123011002.fzcaa3krql3mqsfn@awork3.anarazel.de --- src/tools/pg_bsd_indent/README | 37 ++++++++++++++++++++++++++ src/tools/pg_bsd_indent/args.c | 6 +---- src/tools/pg_bsd_indent/indent.c | 6 +---- src/tools/pg_bsd_indent/indent_codes.h | 6 +---- src/tools/pg_bsd_indent/indent_globs.h | 6 +---- src/tools/pg_bsd_indent/io.c | 6 +---- src/tools/pg_bsd_indent/lexi.c | 6 +---- src/tools/pg_bsd_indent/parse.c | 6 +---- src/tools/pg_bsd_indent/pr_comment.c | 6 +---- 9 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 33d016db62..846855d318 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +The FreeBSD originals of the files in this directory bear the +"4-clause" version of the BSD license. We have removed the +"advertising" clauses, as per UC Berkeley's directive here: +ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change +which reads: + +July 22, 1999 + +To All Licensees, Distributors of Any Version of BSD: + +As you know, certain of the Berkeley Software Distribution ("BSD") source +code files require that further distributions of products containing all or +portions of the software, acknowledge within their advertising materials +that such products contain software developed by UC Berkeley and its +contributors. + +Specifically, the provision reads: + +" * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors." + +Effective immediately, licensees and distributors are no longer required to +include the acknowledgement within advertising materials. Accordingly, the +foregoing paragraph of those BSD Unix files containing it is hereby deleted +in its entirety. + +William Hoskins +Director, Office of Technology Licensing +University of California, Berkeley + +---------- + +What follows is the README file as maintained by FreeBSD indent. + +---------- $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index 1c83f57049..b18eab5d39 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index d3a0ecefe9..0024993844 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h index 24c43fa420..6576bef75d 100644 --- a/src/tools/pg_bsd_indent/indent_codes.h +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h index 398784b3f4..917961bd3d 100644 --- a/src/tools/pg_bsd_indent/indent_globs.h +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c index 3ce8bfb70c..4149424294 100644 --- a/src/tools/pg_bsd_indent/io.c +++ b/src/tools/pg_bsd_indent/io.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c index f01596a870..943bf7ce6b 100644 --- a/src/tools/pg_bsd_indent/lexi.c +++ b/src/tools/pg_bsd_indent/lexi.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c index bf6b1697f9..e707da639c 100644 --- a/src/tools/pg_bsd_indent/parse.c +++ b/src/tools/pg_bsd_indent/parse.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c index b0eacac1bb..a9572b39ff 100644 --- a/src/tools/pg_bsd_indent/pr_comment.c +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * -- 2.31.1 From 3d6bd52162c733bf68e702efae569a945a630e3d Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 18:38:14 -0500 Subject: [PATCH v3 3/3] Integrate pg_bsd_indent into our build/test infrastructure. Update the Makefile and build directions for in-tree build, and add Meson build infrastructure. Also convert the ad-hoc test target into a TAP test. Currently, the Make build system will not build pg_bsd_indent by default, while the Meson system will. Both will test it during "make check-world" or "ninja test". Neither will install it automatically. (We might change some of these decisions later.) Also fix a couple of portability nits noted during early testing. Also, exclude pg_bsd_indent from pgindent's purview; at least for now, we'll leave it formatted similarly to the FreeBSD original. Tom Lane and Andres Freund Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de --- GNUmakefile.in | 2 +- src/Makefile | 2 + src/meson.build | 2 + src/tools/pg_bsd_indent/.gitignore | 12 +--- src/tools/pg_bsd_indent/Makefile | 62 ++++++++++++------- src/tools/pg_bsd_indent/README | 37 +++++++++++ src/tools/pg_bsd_indent/README.pg_bsd_indent | 30 --------- src/tools/pg_bsd_indent/args.c | 2 +- src/tools/pg_bsd_indent/indent.c | 2 +- src/tools/pg_bsd_indent/indent.h | 2 +- src/tools/pg_bsd_indent/meson.build | 40 ++++++++++++ .../pg_bsd_indent/t/001_pg_bsd_indent.pl | 53 ++++++++++++++++ src/tools/pgindent/exclude_file_patterns | 4 ++ 13 files changed, 186 insertions(+), 64 deletions(-) delete mode 100644 src/tools/pg_bsd_indent/README.pg_bsd_indent create mode 100644 src/tools/pg_bsd_indent/meson.build create mode 100644 src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl diff --git a/GNUmakefile.in b/GNUmakefile.in index 5434467381..9c18c56233 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -68,7 +68,7 @@ check check-tests installcheck installcheck-parallel installcheck-tests: CHECKPR check check-tests installcheck installcheck-parallel installcheck-tests: submake-generated-headers $(MAKE) -C src/test/regress $@ -$(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin,check) +$(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin src/tools/pg_bsd_indent,check) $(call recurse,checkprep, src/test src/pl src/interfaces contrib src/bin) $(call recurse,installcheck-world,src/test src/pl src/interfaces contrib src/bin,installcheck) diff --git a/src/Makefile b/src/Makefile index 79e274a476..94649c36c7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -66,11 +66,13 @@ clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ distclean maintainer-clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ rm -f Makefile.port Makefile.global diff --git a/src/meson.build b/src/meson.build index 80fd2823a9..bceeca70f9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -13,6 +13,8 @@ subdir('pl') subdir('interfaces') +subdir('tools/pg_bsd_indent') + ### Generate a Makefile.global that's complete enough for PGXS to work. # diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore index 4c5d8dc691..b27e3610d5 100644 --- a/src/tools/pg_bsd_indent/.gitignore +++ b/src/tools/pg_bsd_indent/.gitignore @@ -1,10 +1,4 @@ -# Global excludes across all subdirectories -*.o -*.obj -*.exe - -# Local excludes in root directory /pg_bsd_indent -/*.out -/*.list -/tests.diff +# Generated by test suite +/log/ +/tmp_check/ diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index ee046f36f0..ee3d494f40 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -1,35 +1,55 @@ #------------------------------------------------------------------------- # -# Makefile for pg_bsd_indent +# src/tools/pg_bsd_indent/Makefile # -# Copyright (c) 2017, PostgreSQL Global Development Group +# Copyright (c) 2017-2023, PostgreSQL Global Development Group # #------------------------------------------------------------------------- PGFILEDESC = "pg_bsd_indent - indent C code nicely" PGAPPICON = win32 -PROGRAM = pg_bsd_indent -OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) +subdir = src/tools/pg_bsd_indent +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global -# clean junk left behind by "make test" -EXTRA_CLEAN = *.out *.list tests.diff +OBJS = \ + $(WIN32RES) \ + args.o \ + err.o \ + indent.o \ + io.o \ + lexi.o \ + parse.o \ + pr_comment.o -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) +all: pg_bsd_indent -# pgxs.mk assumes too much about what "make check" means, so call it "test" +pg_bsd_indent: $(OBJS) | submake-libpgport + $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pg_bsd_indent$(X) '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +clean distclean maintainer-clean: + rm -f pg_bsd_indent$(X) $(OBJS) + rm -rf log/ tmp_check/ + +check: + $(prove_check) + +installcheck: + $(prove_installcheck) + +# Provide this alternate test name to allow testing pg_bsd_indent +# without building all of the surrounding Postgres installation. .PHONY: test -test: $(PROGRAM) - @rm -f tests.diff - @cp $(srcdir)/tests/*.list . - @for testsrc in $(srcdir)/tests/*.0; do \ - test=`basename "$$testsrc" .0`; \ - ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ - diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ - done - @cat tests.diff - @test '!' -s tests.diff - @echo Tests complete. +test: pg_bsd_indent + $(prove_installcheck) diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 846855d318..992d4fce61 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +src/tools/pg_bsd_indent/README + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, configure the surrounding Postgres source tree, +then run "make" in this directory. +Optionally, run "make test" for some simple tests. + +You'll need to install pg_bsd_indent somewhere in your PATH before +using it. Most likely, if you're a developer, you don't want to +put it in the same place as where the surrounding Postgres build +gets installed. Therefore, do this part with something like + + make install prefix=/usr/local + +If you are using Meson to build, the standard build targets will +build pg_bsd_indent and also test it, but there is not currently +provision for installing it anywhere. Manually copy the built +executable from build/src/tools/pg_bsd_indent/pg_bsd_indent to +wherever you want to put it. + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) +We're not planning to re-indent to Postgres style, because that +would make it difficult to compare to the FreeBSD sources. + +---------- + The FreeBSD originals of the files in this directory bear the "4-clause" version of the BSD license. We have removed the "advertising" clauses, as per UC Berkeley's directive here: diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent deleted file mode 100644 index 85c3dcac1c..0000000000 --- a/src/tools/pg_bsd_indent/README.pg_bsd_indent +++ /dev/null @@ -1,30 +0,0 @@ -pg_bsd_indent - -This is a lightly modified version of the "indent" program maintained -by the FreeBSD project. The modifications are mostly to make it portable -to non-BSD-ish platforms, though we do have one formatting switch we -couldn't convince upstream to take. - -To build it, you will need a Postgres installation, version 9.5 or newer. -(Once built, the program doesn't depend on that installation.) - -To build, just say "make"; or if pg_config from your Postgres installation -isn't in your PATH, say - make PG_CONFIG=path/to/pg_config -Optionally, run "make test" for some simple sanity checks. - -To install, copy pg_bsd_indent to somewhere in your usual PATH. -(If you say "make install", it will try to put it in your Postgres -installation directory, which is most likely not what you want for -long-term use.) - -TODO: add build support and instructions for Windows - - -If you happen to be hacking upon the indent source code, the closest -approximation to the existing indentation style seems to be - - ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c - -although this has by no means been rigorously adhered to. -(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index b18eab5d39..d08b086a88 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -176,7 +176,7 @@ void set_profile(const char *profile_name) { FILE *f; - char fname[PATH_MAX]; + char fname[MAXPGPATH]; static char prof[] = ".indent.pro"; if (profile_name == NULL) diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index 0024993844..34205f2ead 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -60,7 +60,7 @@ const char *in_name = "Standard Input"; /* will always point to name of input * file */ const char *out_name = "Standard Output"; /* will always point to name * of output file */ -char bakfile[MAXPATHLEN] = ""; +char bakfile[MAXPGPATH] = ""; int main(int argc, char **argv) diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h index 1708dbc19f..d9fff8ccd6 100644 --- a/src/tools/pg_bsd_indent/indent.h +++ b/src/tools/pg_bsd_indent/indent.h @@ -28,7 +28,7 @@ __FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); #endif -#define nitems(array) (sizeof (array) / sizeof (array[0])) +#define nitems(x) (sizeof((x)) / sizeof((x)[0])) void add_typename(const char *); void alloc_typenames(void); diff --git a/src/tools/pg_bsd_indent/meson.build b/src/tools/pg_bsd_indent/meson.build new file mode 100644 index 0000000000..5545c097bf --- /dev/null +++ b/src/tools/pg_bsd_indent/meson.build @@ -0,0 +1,40 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +pg_bsd_indent_sources = files( + 'args.c', + 'err.c', + 'indent.c', + 'io.c', + 'lexi.c', + 'parse.c', + 'pr_comment.c', +) + +if host_system == 'windows' + pg_bsd_indent_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'pg_bsd_indent', + '--FILEDESC', 'pg_bsd_indent - indent C code nicely']) +endif + +pg_bsd_indent = executable('pg_bsd_indent', + pg_bsd_indent_sources, + dependencies: [frontend_code], + include_directories: include_directories('.'), + kwargs: default_bin_args + { + 'install': false, +# possibly at some point do this: +# 'install_dir': dir_pgxs / 'src/tools/pg_bsd_indent', + }, +) +bin_targets += pg_bsd_indent + +tests += { + 'name': 'pg_bsd_indent', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_pg_bsd_indent.pl', + ], + }, +} diff --git a/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl new file mode 100644 index 0000000000..b40b3fdbbf --- /dev/null +++ b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl @@ -0,0 +1,53 @@ +# pg_bsd_indent: some simple tests + +# The test cases come from FreeBSD upstream, but this test scaffolding is ours. +# Copyright (c) 2017-2023, PostgreSQL Global Development Group + +use strict; +use warnings; + +use Cwd qw(getcwd); +use File::Copy "cp"; +use File::Spec; + +use PostgreSQL::Test::Utils; +use Test::More; + +# We expect to be started in the source directory (even in a VPATH build); +# we want to run pg_bsd_indent in the tmp_check directory to reduce clutter. +# (Also, it's caller's responsibility that pg_bsd_indent be in the PATH.) +my $src_dir = getcwd; +chdir ${PostgreSQL::Test::Utils::tmp_check}; + +# Basic tests: pg_bsd_indent knows --version but not much else. +program_version_ok('pg_bsd_indent'); + +# Run pg_bsd_indent on pre-fab test cases. +# Any diffs in the generated files will be accumulated here. +my $diff_file = "tests.diff"; + +# Copy support files to current dir, so *.pro files don't need to know path. +while (my $file = glob("$src_dir/tests/*.list")) +{ + cp($file, ".") || die "cp $file failed: $!"; +} + +while (my $test_src = glob("$src_dir/tests/*.0")) +{ + # extract test basename + my ($volume, $directories, $test) = File::Spec->splitpath($test_src); + $test =~ s/\.0$//; + # run pg_bsd_indent + command_ok( + [ + 'pg_bsd_indent', $test_src, + "$test.out", "-P$src_dir/tests/$test.pro" + ], + "pg_bsd_indent succeeds on $test"); + # check result matches, adding any diff to $diff_file + my $result = run_log([ 'diff', '-upd', "$test_src.stdout", "$test.out" ], + '>>', $diff_file); + ok($result, "pg_bsd_indent output matches for $test"); +} + +done_testing(); diff --git a/src/tools/pgindent/exclude_file_patterns b/src/tools/pgindent/exclude_file_patterns index f5c8857e31..6405a00511 100644 --- a/src/tools/pgindent/exclude_file_patterns +++ b/src/tools/pgindent/exclude_file_patterns @@ -47,6 +47,10 @@ src/pl/plperl/ppport\.h$ src/pl/plperl/SPI\.c$ src/pl/plperl/Util\.c$ # +# pg_bsd_indent has its own, idiosyncratic indentation style. +# We'll stick to that to permit comparison with the FreeBSD upstream. +src/tools/pg_bsd_indent/.* +# # Exclude any temporary installations that may be in the tree. /tmp_check/ /tmp_install/ -- 2.31.1
I wrote: > I'll let the cfbot loose on this, and if it runs the tests > successfully I plan to go ahead and push. cfbot didn't like that ... regards, tom lane From 55d1373fb0f7df6745ef8c34274bc82cb84d15d0 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 14:06:36 -0500 Subject: [PATCH v3 1/4] Import pg_bsd_indent sources. This brings in an exact copy of the pg_bsd_indent repo as of commit d301442799cea44e5ccb04331afc537764ec77c5 (2020-12-28). Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de --- src/tools/pg_bsd_indent/.gitignore | 10 + src/tools/pg_bsd_indent/Makefile | 35 + src/tools/pg_bsd_indent/README | 100 ++ src/tools/pg_bsd_indent/README.pg_bsd_indent | 30 + src/tools/pg_bsd_indent/args.c | 354 +++++ src/tools/pg_bsd_indent/err.c | 67 + src/tools/pg_bsd_indent/err.h | 45 + src/tools/pg_bsd_indent/indent.1 | 618 ++++++++ src/tools/pg_bsd_indent/indent.c | 1279 +++++++++++++++++ src/tools/pg_bsd_indent/indent.h | 51 + src/tools/pg_bsd_indent/indent_codes.h | 75 + src/tools/pg_bsd_indent/indent_globs.h | 343 +++++ src/tools/pg_bsd_indent/io.c | 608 ++++++++ src/tools/pg_bsd_indent/lexi.c | 724 ++++++++++ src/tools/pg_bsd_indent/parse.c | 342 +++++ src/tools/pg_bsd_indent/pr_comment.c | 358 +++++ src/tools/pg_bsd_indent/tests/binary.0 | 9 + src/tools/pg_bsd_indent/tests/binary.0.stdout | 11 + src/tools/pg_bsd_indent/tests/comments.0 | 52 + .../pg_bsd_indent/tests/comments.0.stdout | 60 + src/tools/pg_bsd_indent/tests/comments.pro | 1 + src/tools/pg_bsd_indent/tests/cppelsecom.0 | 7 + .../pg_bsd_indent/tests/cppelsecom.0.stdout | 7 + src/tools/pg_bsd_indent/tests/declarations.0 | 79 + .../pg_bsd_indent/tests/declarations.0.stdout | 73 + src/tools/pg_bsd_indent/tests/elsecomment.0 | 42 + .../pg_bsd_indent/tests/elsecomment.0.stdout | 47 + src/tools/pg_bsd_indent/tests/elsecomment.pro | 1 + src/tools/pg_bsd_indent/tests/enum.0 | 6 + src/tools/pg_bsd_indent/tests/enum.0.stdout | 5 + src/tools/pg_bsd_indent/tests/f_decls.0 | 27 + .../pg_bsd_indent/tests/f_decls.0.stdout | 30 + src/tools/pg_bsd_indent/tests/float.0 | 6 + src/tools/pg_bsd_indent/tests/float.0.stdout | 8 + src/tools/pg_bsd_indent/tests/label.0 | 13 + src/tools/pg_bsd_indent/tests/label.0.stdout | 14 + src/tools/pg_bsd_indent/tests/label.pro | 1 + src/tools/pg_bsd_indent/tests/list_head.0 | 15 + .../pg_bsd_indent/tests/list_head.0.stdout | 13 + src/tools/pg_bsd_indent/tests/nsac.0 | 4 + src/tools/pg_bsd_indent/tests/nsac.0.stdout | 6 + src/tools/pg_bsd_indent/tests/nsac.pro | 1 + src/tools/pg_bsd_indent/tests/offsetof.0 | 5 + .../pg_bsd_indent/tests/offsetof.0.stdout | 7 + src/tools/pg_bsd_indent/tests/parens.0 | 26 + src/tools/pg_bsd_indent/tests/parens.0.stdout | 26 + src/tools/pg_bsd_indent/tests/parens.pro | 1 + src/tools/pg_bsd_indent/tests/sac.0 | 4 + src/tools/pg_bsd_indent/tests/sac.0.stdout | 6 + src/tools/pg_bsd_indent/tests/sac.pro | 1 + src/tools/pg_bsd_indent/tests/struct.0 | 21 + src/tools/pg_bsd_indent/tests/struct.0.stdout | 23 + src/tools/pg_bsd_indent/tests/surplusbad.0 | 9 + .../pg_bsd_indent/tests/surplusbad.0.stdout | 9 + src/tools/pg_bsd_indent/tests/surplusbad.pro | 1 + .../pg_bsd_indent/tests/types_from_file.0 | 3 + .../tests/types_from_file.0.stdout | 3 + .../pg_bsd_indent/tests/types_from_file.list | 2 + .../pg_bsd_indent/tests/types_from_file.pro | 1 + src/tools/pg_bsd_indent/tests/wchar.0 | 6 + src/tools/pg_bsd_indent/tests/wchar.0.stdout | 6 + 61 files changed, 5737 insertions(+) create mode 100644 src/tools/pg_bsd_indent/.gitignore create mode 100644 src/tools/pg_bsd_indent/Makefile create mode 100644 src/tools/pg_bsd_indent/README create mode 100644 src/tools/pg_bsd_indent/README.pg_bsd_indent create mode 100644 src/tools/pg_bsd_indent/args.c create mode 100644 src/tools/pg_bsd_indent/err.c create mode 100644 src/tools/pg_bsd_indent/err.h create mode 100644 src/tools/pg_bsd_indent/indent.1 create mode 100644 src/tools/pg_bsd_indent/indent.c create mode 100644 src/tools/pg_bsd_indent/indent.h create mode 100644 src/tools/pg_bsd_indent/indent_codes.h create mode 100644 src/tools/pg_bsd_indent/indent_globs.h create mode 100644 src/tools/pg_bsd_indent/io.c create mode 100644 src/tools/pg_bsd_indent/lexi.c create mode 100644 src/tools/pg_bsd_indent/parse.c create mode 100644 src/tools/pg_bsd_indent/pr_comment.c create mode 100644 src/tools/pg_bsd_indent/tests/binary.0 create mode 100644 src/tools/pg_bsd_indent/tests/binary.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/comments.0 create mode 100644 src/tools/pg_bsd_indent/tests/comments.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/comments.pro create mode 100644 src/tools/pg_bsd_indent/tests/cppelsecom.0 create mode 100644 src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/declarations.0 create mode 100644 src/tools/pg_bsd_indent/tests/declarations.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.0 create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.pro create mode 100644 src/tools/pg_bsd_indent/tests/enum.0 create mode 100644 src/tools/pg_bsd_indent/tests/enum.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/f_decls.0 create mode 100644 src/tools/pg_bsd_indent/tests/f_decls.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/float.0 create mode 100644 src/tools/pg_bsd_indent/tests/float.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/label.0 create mode 100644 src/tools/pg_bsd_indent/tests/label.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/label.pro create mode 100644 src/tools/pg_bsd_indent/tests/list_head.0 create mode 100644 src/tools/pg_bsd_indent/tests/list_head.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/nsac.0 create mode 100644 src/tools/pg_bsd_indent/tests/nsac.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/nsac.pro create mode 100644 src/tools/pg_bsd_indent/tests/offsetof.0 create mode 100644 src/tools/pg_bsd_indent/tests/offsetof.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/parens.0 create mode 100644 src/tools/pg_bsd_indent/tests/parens.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/parens.pro create mode 100644 src/tools/pg_bsd_indent/tests/sac.0 create mode 100644 src/tools/pg_bsd_indent/tests/sac.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/sac.pro create mode 100644 src/tools/pg_bsd_indent/tests/struct.0 create mode 100644 src/tools/pg_bsd_indent/tests/struct.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.0 create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.pro create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.0 create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.list create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.pro create mode 100644 src/tools/pg_bsd_indent/tests/wchar.0 create mode 100644 src/tools/pg_bsd_indent/tests/wchar.0.stdout diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore new file mode 100644 index 0000000000..4c5d8dc691 --- /dev/null +++ b/src/tools/pg_bsd_indent/.gitignore @@ -0,0 +1,10 @@ +# Global excludes across all subdirectories +*.o +*.obj +*.exe + +# Local excludes in root directory +/pg_bsd_indent +/*.out +/*.list +/tests.diff diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile new file mode 100644 index 0000000000..ee046f36f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/Makefile @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------- +# +# Makefile for pg_bsd_indent +# +# Copyright (c) 2017, PostgreSQL Global Development Group +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pg_bsd_indent - indent C code nicely" +PGAPPICON = win32 + +PROGRAM = pg_bsd_indent +OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) + +# clean junk left behind by "make test" +EXTRA_CLEAN = *.out *.list tests.diff + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) + +# pgxs.mk assumes too much about what "make check" means, so call it "test" +.PHONY: test + +test: $(PROGRAM) + @rm -f tests.diff + @cp $(srcdir)/tests/*.list . + @for testsrc in $(srcdir)/tests/*.0; do \ + test=`basename "$$testsrc" .0`; \ + ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ + diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ + done + @cat tests.diff + @test '!' -s tests.diff + @echo Tests complete. diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README new file mode 100644 index 0000000000..33d016db62 --- /dev/null +++ b/src/tools/pg_bsd_indent/README @@ -0,0 +1,100 @@ + + $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ + +This is the C indenter, it originally came from the University of Illinois +via some distribution tape for PDP-11 Unix. It has subsequently been +hacked upon by James Gosling @ CMU. It isn't very pretty, and really needs +to be completely redone, but it is probably the nicest C pretty printer +around. + +Further additions to provide "Kernel Normal Form" were contributed +by the folks at Sun Microsystems. + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +> From mnetor!yunexus!oz@uunet.UU.NET Wed Mar 9 15:30:55 1988 +> Date: Tue, 8 Mar 88 18:36:25 EST +> From: yunexus!oz@uunet.UU.NET (Ozan Yigit) +> To: bostic@okeeffe.berkeley.edu +> Cc: ccvaxa!willcox@uunet.UU.NET, jag@sun.com, rsalz@uunet.UU.NET +> In-Reply-To: Keith Bostic's message of Tue, 16 Feb 88 16:09:06 PST +> Subject: Re: Indent... + +Thank you for your response about indent. I was wrong in my original +observation (or mis-observation :-). UCB did keep the Illinois +copyright intact. + +The issue still is whether we can distribute indent, and if we can, which +version. David Willcox (the author) states that: + +| Several people have asked me on what basis I claim that indent is in +| the public domain. I knew I would be sorry I made that posting. +| +| Some history. Way back in 1976, the project I worked on at the +| University of Illinois Center for Advanced Computation had a huge +| battle about how to format C code. After about a week of fighting, I +| got disgusted and wrote a program, which I called indent, to reformat C +| code. It had a bunch of different options that would let you format +| the output the way you liked. In particular, all of the different +| formats being championed were supported. +| +| It was my first big C program. It was ugly. It wasn't designed, it +| just sort of grew. But it pretty much worked, and it stopped most of +| the fighting. +| +| As a matter of form, I included a University of Illinois Copyright +| notice. However, my understanding was that, since the work was done +| on an ARPA contract, it was in the public domain. +| +| Time passed. Some years later, indent showed up on one of the early +| emacs distributions. +| +| Later still, someone from UC Berkeley called the UofI and asked if +| indent was in the public domain. They wanted to include it in their +| UNIX distributions, along with the emacs stuff. I was no longer at the +| UofI, but Rob Kolstad, who was, asked me about it. I told him I didn't +| care if they used it, and since then it has been on the BSD distributions. +| +| Somewhere along the way, several other unnamed people have had their +| hands in it. It was converted to understand version 7 C. (The +| original was version 6.) It was converted from its original filter +| interface to its current "blow away the user's file" interface. +| The $HOME/.indent.pro file parsing was added. Some more formatting +| options were added. +| +| The source I have right now has two copyright notices. One is the +| original from the UofI. One is from Berkeley. +| +| I am not a lawyer, and I certainly do not understand copyright law. As +| far as I am concerned, the bulk of this program, everything covered by +| the UofI copyright, is in the public domain, and worth every penny. +| Berkeley's copyright probably should only cover their changes, and I +| don't know their feelings about sending it out. + +In any case, there appears to be none at UofI to clarify/and change +that copyright, but I am confident (based on the statements of its +author) that the code, as it stands with its copyright, is +distributable, and will not cause any legal problems. + +Hence, the issue reduces to *which* one to distribute through +comp.sources.unix. I would suggest that with the permission of you +folks (given that you have parts copyrighted), we distribute the 4.3 +version of indent, which appears to be the most up-to-date version. I +happen to have just about every known version of indent, including the +very original submission from the author to a unix tape, later the +G-Emacs version, any 4.n version, sun version and the Unipress +version. I still think we should not have to "go-back-in-time" and +re-do all the work you people have done. + +I hope to hear from you as to what you think about this. You may of +course send 4.3 version to the moderator directly, or you can let me +know of your permission, and I will send the sources, or you can let +me know that 4.3 version is off-limits, in which case we would probably +have to revert to an older version. One way or another, I hope to get +a version of indent to comp.sources.unix. + +regards.. oz + +cc: ccvaxa!willcox + sun.com!jar + uunet!rsalz + diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent new file mode 100644 index 0000000000..85c3dcac1c --- /dev/null +++ b/src/tools/pg_bsd_indent/README.pg_bsd_indent @@ -0,0 +1,30 @@ +pg_bsd_indent + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, you will need a Postgres installation, version 9.5 or newer. +(Once built, the program doesn't depend on that installation.) + +To build, just say "make"; or if pg_config from your Postgres installation +isn't in your PATH, say + make PG_CONFIG=path/to/pg_config +Optionally, run "make test" for some simple sanity checks. + +To install, copy pg_bsd_indent to somewhere in your usual PATH. +(If you say "make install", it will try to put it in your Postgres +installation directory, which is most likely not what you want for +long-term use.) + +TODO: add build support and instructions for Windows + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c new file mode 100644 index 0000000000..1c83f57049 --- /dev/null +++ b/src/tools/pg_bsd_indent/args.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include <ctype.h> +#include <err.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +#define INDENT_VERSION "2.1.1" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +static void scan_profile(FILE *); + +#define KEY_FILE 5 /* only used for args */ +#define VERSION 6 /* only used for args */ + +const char *option_source = "?"; + +void add_typedefs_from_file(const char *str); + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + const char *p_name; /* name, e.g. -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + {"T", PRO_SPECIAL, 0, KEY, 0}, + {"U", PRO_SPECIAL, 0, KEY_FILE, 0}, + {"-version", PRO_SPECIAL, 0, VERSION, 0}, + {"P", PRO_SPECIAL, 0, IGN, 0}, + {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation}, + {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop}, + {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations}, + {"bap", PRO_BOOL, false, ON, &blanklines_after_procs}, + {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments}, + {"bc", PRO_BOOL, true, OFF, &ps.leave_comma}, + {"bl", PRO_BOOL, true, OFF, &btype_2}, + {"br", PRO_BOOL, true, ON, &btype_2}, + {"bs", PRO_BOOL, false, ON, &Bill_Shannon}, + {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline}, + {"cd", PRO_INT, 0, 0, &ps.decl_com_ind}, + {"ce", PRO_BOOL, true, ON, &cuddle_else}, + {"ci", PRO_INT, 0, 0, &continuation_indent}, + {"cli", PRO_SPECIAL, 0, CLI, 0}, + {"cp", PRO_INT, 0, 0, &else_endif_com_ind}, + {"c", PRO_INT, 33, 0, &ps.com_ind}, + {"di", PRO_INT, 16, 0, &ps.decl_indent}, + {"dj", PRO_BOOL, false, ON, &ps.ljust_decl}, + {"d", PRO_INT, 0, 0, &ps.unindent_displace}, + {"eei", PRO_BOOL, false, ON, &extra_expression_indent}, + {"ei", PRO_BOOL, true, ON, &ps.else_if}, + {"fbs", PRO_BOOL, true, ON, &function_brace_split}, + {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, + {"fcb", PRO_BOOL, true, ON, &format_block_comments}, + {"ip", PRO_BOOL, true, ON, &ps.indent_parameters}, + {"i", PRO_INT, 8, 0, &ps.ind_size}, + {"lc", PRO_INT, 0, 0, &block_comment_max_col}, + {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent}, + {"lpl", PRO_BOOL, false, ON, &lineup_to_parens_always}, + {"lp", PRO_BOOL, true, ON, &lineup_to_parens}, + {"l", PRO_INT, 78, 0, &max_col}, + {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation}, + {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop}, + {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations}, + {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs}, + {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments}, + {"nbc", PRO_BOOL, true, ON, &ps.leave_comma}, + {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon}, + {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline}, + {"nce", PRO_BOOL, true, OFF, &cuddle_else}, + {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl}, + {"neei", PRO_BOOL, false, OFF, &extra_expression_indent}, + {"nei", PRO_BOOL, true, OFF, &ps.else_if}, + {"nfbs", PRO_BOOL, true, OFF, &function_brace_split}, + {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments}, + {"nfcb", PRO_BOOL, true, OFF, &format_block_comments}, + {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters}, + {"nlpl", PRO_BOOL, false, OFF, &lineup_to_parens_always}, + {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens}, + {"npcs", PRO_BOOL, false, OFF, &proc_calls_space}, + {"npro", PRO_SPECIAL, 0, IGN, 0}, + {"npsl", PRO_BOOL, true, OFF, &procnames_start_line}, + {"nsac", PRO_BOOL, false, OFF, &space_after_cast}, + {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, + {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, + {"ntpg", PRO_BOOL, false, OFF, &postgres_tab_rules}, + {"nut", PRO_BOOL, true, OFF, &use_tabs}, + {"nv", PRO_BOOL, false, OFF, &verbose}, + {"pcs", PRO_BOOL, false, ON, &proc_calls_space}, + {"psl", PRO_BOOL, true, ON, &procnames_start_line}, + {"sac", PRO_BOOL, false, ON, &space_after_cast}, + {"sc", PRO_BOOL, true, ON, &star_comment_cont}, + {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines}, + {"st", PRO_SPECIAL, 0, STDIN, 0}, + {"ta", PRO_BOOL, false, ON, &auto_typedefs}, + {"tpg", PRO_BOOL, false, ON, &postgres_tab_rules}, + {"ts", PRO_INT, 8, 0, &tabsize}, + {"ut", PRO_BOOL, true, ON, &use_tabs}, + {"v", PRO_BOOL, false, ON, &verbose}, + /* whew! */ + {0, 0, 0, 0, 0} +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +void +set_profile(const char *profile_name) +{ + FILE *f; + char fname[PATH_MAX]; + static char prof[] = ".indent.pro"; + + if (profile_name == NULL) + snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); + else + snprintf(fname, sizeof(fname), "%s", profile_name + 2); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +static void +scan_profile(FILE *f) +{ + int comment, i; + char *p; + char buf[BUFSIZ]; + + while (1) { + p = buf; + comment = 0; + while ((i = getc(f)) != EOF) { + if (i == '*' && !comment && p > buf && p[-1] == '/') { + comment = p - buf; + *p++ = i; + } else if (i == '/' && comment && p > buf && p[-1] == '*') { + p = buf + comment - 1; + comment = 0; + } else if (isspace((unsigned char)i)) { + if (p > buf && !comment) + break; + } else { + *p++ = i; + } + } + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +static const char * +eqin(const char *s1, const char *s2) +{ + while (*s1) { + if (*s1++ != *s2++) + return (NULL); + } + return (s2); +} + +/* + * Set the defaults. + */ +void +set_defaults(void) +{ + struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL) + *p->p_obj = p->p_default; +} + +void +set_option(char *arg) +{ + struct pro *p; + const char *param_start; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL) + goto found; + errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == NULL) + input = stdin; + if (output == NULL) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + add_typename(param_start); + break; + + case KEY_FILE: + if (*param_start == 0) + goto need_param; + add_typedefs_from_file(param_start); + break; + + case VERSION: + printf("pg_bsd_indent %s (based on FreeBSD indent)\n", INDENT_VERSION); + exit(0); + + default: + errx(1, "set_option: internal error: p_special %d", p->p_special); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit((unsigned char)*param_start)) { + need_param: + errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name); + } + *p->p_obj = atoi(param_start); + break; + + default: + errx(1, "set_option: internal error: p_type %d", p->p_type); + } +} + +void +add_typedefs_from_file(const char *str) +{ + FILE *file; + char line[BUFSIZ]; + + if ((file = fopen(str, "r")) == NULL) { + fprintf(stderr, "indent: cannot open file %s\n", str); + exit(1); + } + while ((fgets(line, BUFSIZ, file)) != NULL) { + /* Remove trailing whitespace */ + line[strcspn(line, " \t\n\r")] = '\0'; + add_typename(line); + } + fclose(file); +} diff --git a/src/tools/pg_bsd_indent/err.c b/src/tools/pg_bsd_indent/err.c new file mode 100644 index 0000000000..807319334b --- /dev/null +++ b/src/tools/pg_bsd_indent/err.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This is cut down to just the minimum that we need to build indent. + */ +#include "c.h" + +#include <err.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void +err(int eval, const char *fmt, ...) +{ + int code = errno; + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); + va_end(ap); + exit(eval); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(eval); +} diff --git a/src/tools/pg_bsd_indent/err.h b/src/tools/pg_bsd_indent/err.h new file mode 100644 index 0000000000..a3e8f97825 --- /dev/null +++ b/src/tools/pg_bsd_indent/err.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: stable/11/include/err.h 203964 2010-02-16 19:39:50Z imp $ + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * This is cut down to just the minimum that we need to build indent. + */ + +void err(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); +void errx(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); + +#endif /* !_ERR_H_ */ diff --git a/src/tools/pg_bsd_indent/indent.1 b/src/tools/pg_bsd_indent/indent.1 new file mode 100644 index 0000000000..131abfe70b --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.1 @@ -0,0 +1,618 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)indent.1 8.1 (Berkeley) 7/1/93 +.\" $FreeBSD: head/usr.bin/indent/indent.1 309524 2016-12-04 03:10:25Z pfg $ +.\" +.Dd December 2, 2016 +.Dt INDENT 1 +.Os +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm +.Op Ar input-file Op Ar output-file +.Op Fl bacc | Fl nbacc +.Op Fl bad | Fl nbad +.Op Fl badp | Fl nbadp +.Op Fl bap | Fl nbap +.Op Fl bbb | Fl nbbb +.Op Fl \&bc | Fl nbc +.Op Fl \&bl | Fl \&br +.Op Fl bs | Fl nbs +.Op Fl c Ns Ar n +.Op Fl cp Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Op Fl dj | Fl ndj +.Bk -words +.Op Fl ei | Fl nei +.Op Fl eei | Fl neei +.Ek +.Bk -words +.Op Fl fbs | Fl nfbs +.Op Fl fc1 | Fl nfc1 +.Op Fl fcb | Fl nfcb +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&ldi Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl \&lpl | Fl nlpl +.Op Fl npro +.Op Fl P Ns Ar file +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl sac | Fl nsac +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl \&ta +.Op Fl T Ns Ar typename +.Op Fl tpg | Fl ntpg +.Op Fl ts Ns Ar n +.Op Fl U Ns Ar file +.Op Fl ut | Fl nut +.Op Fl v | Fl \&nv +.Op Fl -version +.Sh DESCRIPTION +The +.Nm +utility is a +.Em C +program formatter. +It reformats the +.Em C +program in the +.Ar input-file +according to the switches. +The switches which can be +specified are described below. +They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input-file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input-file +and a backup copy of +.Ar input-file +is written in the current directory. +If +.Ar input-file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Sq Pa file.BAK . +.Pp +If +.Ar output-file +is specified, +.Nm +checks to make sure that it is different from +.Ar input-file . +.Pp +The options listed below control the formatting style imposed by +.Nm . +.Bl -tag -width Op +.It Fl bacc , nbacc +If +.Fl bacc +is specified, a blank line is forced around every conditional +compilation block. +For example, in front of every #ifdef and after every #endif. +Other blank lines surrounding such blocks will be swallowed. +Default: +.Fl nbacc . +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. +Default: +.Fl nbad . +.It Fl badp , nbadp +This is vaguely similar to +.Fl bad +except that it only applies to the first set of declarations +in a procedure (just after the first `{') and it causes a blank +line to be generated even if there are no declarations. +The default is +.Fl nbadp. +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. +Default: +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. +Default: +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. +Default: +.Fl \&nbc . +.It Fl \&bl , \&br +Specifying +.Fl \&bl +lines up compound statements like this: +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.It Fl bs , nbs +Whether a blank should always be inserted after sizeof. +The default is +.Fl nbs. +.It Fl c Ns Ar n +The column in which comments on code start. +The default is 33. +.It Fl cp Ns Ar n +The column in which comments on #else and #endif start. +The default is 0, which effectively separates the directives from comments by +a single space. +.It Fl cd Ns Ar n +The column in which comments on declarations start. +The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. +With +this option enabled, comments look like this: +.Bd -literal -offset indent + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. +The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing of `else's to cuddle up to the immediately preceding +`}'. +The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. +Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect +or the continuation indent is exactly half of the main indent. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0.5 +causes case labels to be indented half a tab stop. +The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. +For example, +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. +Specifying the default +.Fl \&d\&0 +lines up these comments with the code. +See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, +of global variable names and all struct/union member names +relative to the beginning of their type declaration. +The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. +The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. +If it is enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +The default is +.Fl ei . +.It Fl eei , neei +Enables (disables) extra indentation on continuation lines of +the expression part of +.Ic if +and +.Ic while +statements. +These continuation lines will be indented one extra level. +The default is +.Fl neei . +.It Fl fbs , nfbs +Enables (disables) splitting the function declaration and opening brace +across two lines. +The default is +.Fl fbs . +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. +In such cases, +.Fl nfc1 +should be +used. +The default is +.Fl fc1 . +.It Fl fcb , nfcb +Enables (disables) the formatting of block comments (ones that begin +with `/*\\n'). +Often, block comments have been not so carefully hand formatted by the +programmer, but reformatting that would just change the line breaks is not +wanted. +In such cases, +.Fl nfcb +should be used. +Block comments are then handled like box comments. +The default is +.Fl fcb . +.It Fl i Ns Ar n +The number of columns for one indentation level. +The default is 8. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. +The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. +The default is 78. +.It Fl lc Ns Ar n +Maximum length of an output line in a block comment. +The default is 0, which means to limit block comment lines in accordance with +.Fl l. +.It Fl \&ldi Ns Ar n +Specifies the indentation, in character positions, +of local variable names +relative to the beginning of their type declaration. +The default is for local variable names to be indented +by the same amount as global ones. +.It Fl \&lp , nlp +Lines up code surrounded by parentheses in continuation lines. +With +.Fl \&lp , +if a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. +For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.Bd -literal -offset indent +p1 = first_procedure(second_procedure(p2, p3), +\ \ third_procedure(p4, p5)); +.Ed +.Pp +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2,\ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5)); +.Ed +.Pp +Inserting two more newlines we get: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl \&lpl , nlpl +With +.Fl \&lpl , +code surrounded by parentheses in continuation lines is lined up even if it +would extend past the right margin. +With +.Fl \&nlpl +(the default), such a line that would extend past the right margin is moved +left to keep it within the margin, if that does not require placing it to +the left of the prevailing indentation level. +These switches have no effect if +.Fl nlp +is selected. +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl P Ns Ar file +Read profile from +.Ar file . +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. +The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. +The +default is +.Fl psl . +.It Fl sac , nsac +Control whether parenthesized type names in casts are followed by a space or +not. +The default is +.Fl nsac . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +The default is +.Fl sc . +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. +You can use this to +get rid of blank lines after declarations. +Default: +.Fl nsob . +.It Fl \&st +Causes +.Nm +to take its input from stdin and put its output to stdout. +.It Fl ta +Automatically add all identifiers ending in "_t" to the list +of type keywords. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. +Names accumulate: +.Fl T +can be specified more than once. +You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program will not be formatted as nicely as +it should. +This sounds like a painful thing to have to do, but it is really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm +cannot find all +instances of +.Ic typedef . +.It Fl tpg , ntpg +If +.Fl tpg +is specified, follow Postgres rules about when to use spaces versus +tabs for indentation, that is, use a space instead of a tab if the +tab would move only one column and no tab will follow it. +Default: +.Fl ntpg . +.It Fl ts Ns Ar n +Assumed distance between tab stops. +The default is 8. +.It Fl U Ns Ar file +Adds type names from +.Ar file +to the list of type keywords. +.It Fl ut , nut +Enables (disables) the use of tab characters in the output. +The default is +.Fl ut . +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. +When in verbose mode, +.Nm +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. +The default is +.Fl \&nv . +.It Fl -version +Causes +.Nm +to print its version number and exit. +.El +.Pp +You may set up your own `profile' of defaults to +.Nm +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. +A `.indent.pro' in the current directory takes +precedence over the one in your login directory. +If +.Nm +is run and a profile file exists, then it is read to set up the program's +defaults. +Switches on the command line, though, always override profile +switches. +The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +The +.Nm +utility +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +The +.Nm +utility fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. +Blank lines break paragraphs. +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. +Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. +If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Ss Preprocessor lines +In general, +.Nm +leaves preprocessor lines alone. +The only +reformatting that it will do is to straighten up trailing comments. +It +leaves embedded comments alone. +Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Ss C syntax +The +.Nm +utility understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. +It attempts to cope with the usual sorts of +incomplete and malformed syntax. +In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +The +.Nm +utility uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +The +.Nm +utility has even more switches than +.Xr ls 1 . +.Pp +A common mistake is to try to indent all the +.Em C +programs in a directory by typing: +.Pp +.Dl indent *.c +.Pp +This is probably a bug, not a feature. diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c new file mode 100644 index 0000000000..d3a0ecefe9 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.c @@ -0,0 +1,1279 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <sys/param.h> +#include <err.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +/* Tell indent_globs.h to define our global variables here */ +#define DECLARE_INDENT_GLOBALS 1 + +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void bakcopy(void); +static void indent_declaration(int, int); + +const char *in_name = "Standard Input"; /* will always point to name of input + * file */ +const char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +int +main(int argc, char **argv) +{ + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int force_nl; /* when true, code must be broken */ + int hd_type = 0; /* used to store type of stmt for if (...), + * for (...), etc */ + int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expression of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a <c>?<s>:<s> + * construct */ + const char *t_ptr; /* used for copying tokens */ + int tabs_to_var; /* true if using tabs to indent to var name */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + const char *profile_name = NULL; + struct parser_state transient_state; /* a copy for lookup */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + found_err = 0; + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + if (combuf == NULL) + err(1, NULL); + labbuf = (char *) malloc(bufsize); + if (labbuf == NULL) + err(1, NULL); + codebuf = (char *) malloc(bufsize); + if (codebuf == NULL) + err(1, NULL); + tokenbuf = (char *) malloc(bufsize); + if (tokenbuf == NULL) + err(1, NULL); + alloc_typenames(); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + if (in_buffer == NULL) + err(1, NULL); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + scase = ps.pcase = false; + squest = 0; + sc_end = NULL; + bp_save = NULL; + be_save = NULL; + + output = NULL; + tabs_to_var = 0; + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + lineup_to_parens_always = 0; /* -nlpl */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.local_decl_indent = -1; /* if this is not set to some nonnegative value + * by an arg, we will set this equal to + * ps.decl_ind */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_block_comments = 1; /* -fcb */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0') + profile_name = argv[i]; /* non-empty -P (set profile) */ + set_defaults(); + if (i >= argc) + set_profile(profile_name); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == NULL) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == NULL) /* check for open error */ + err(1, "%s", in_name); + continue; + } + else if (output == NULL) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + errx(1, "input and output files must be different"); + } + output = fopen(out_name, "w"); + if (output == NULL) /* check for create error */ + err(1, "%s", out_name); + continue; + } + errx(1, "unknown parameter: %s", argv[i]); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == NULL) + input = stdin; + if (output == NULL) { + if (input == stdin) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + } + + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.local_decl_indent < 0) /* if not specified by user, set this */ + ps.local_decl_indent = ps.decl_indent; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + char *p = buf_ptr; + int col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = tabsize * (1 + (col - 1) / tabsize) + 1; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int comment_buffered = false; + + type_code = lexi(&ps); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + + /* + * The following code moves newlines and comments following an if (), + * while (), else, etc. up to the start of the following stmt to + * a buffer. This allows proper handling of both kinds of brace + * placement (-br, -bl) and cuddling "else" (-ce). + */ + + while (ps.search_brace) { + switch (type_code) { + case newline: + if (sc_end == NULL) { + save_com = sc_buf; + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + *sc_end++ = '\n'; + /* + * We may have inherited a force_nl == true from the previous + * token (like a semicolon). But once we know that a newline + * has been scanned in this loop, force_nl should be false. + * + * However, the force_nl == true must be preserved if newline + * is never scanned in this loop, so this assignment cannot be + * done earlier. + */ + force_nl = false; + case form_feed: + break; + case comment: + if (sc_end == NULL) { + /* + * Copy everything from the start of the line, because + * pr_comment() will use that to calculate original + * indentation of a boxed comment. + */ + memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4); + save_com = sc_buf + (buf_ptr - in_buffer - 4); + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + comment_buffered = true; + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + if (sc_end >= &save_com[sc_size]) { /* check for temp buffer + * overflow */ + diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + case lbrace: + /* + * Put KNF-style lbraces before the buffered up tokens and + * jump out of this loop in order to avoid copying the token + * again under the default case of the switch below. + */ + if (sc_end != NULL && btype_2) { + save_com[0] = '{'; + /* + * Originally the lbrace may have been alone on its own + * line, but it will be moved into "the else's line", so + * if there was a newline resulting from the "{" before, + * it must be scanned now and ignored. + */ + while (isspace((unsigned char)*buf_ptr)) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '\n') + break; + } + goto sw_buffer; + } + /* FALLTHROUGH */ + default: /* it is the start of a normal statement */ + { + int remove_newlines; + + remove_newlines = + /* "} else" */ + (type_code == sp_nparen && *token == 'e' && + e_code != s_code && e_code[-1] == '}') + /* "else if" */ + || (type_code == sp_paren && *token == 'i' && + last_else && ps.else_if); + if (remove_newlines) + force_nl = false; + if (sc_end == NULL) { /* ignore buffering if + * comment wasn't saved up */ + ps.search_brace = false; + goto check_type; + } + while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) { + sc_end--; + } + if (swallow_optional_blanklines || + (!comment_buffered && remove_newlines)) { + force_nl = !remove_newlines; + while (sc_end > save_com && sc_end[-1] == '\n') { + sc_end--; + } + } + if (force_nl) { /* if we should insert a nl here, put + * it into the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the + * newline is read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose) /* print error msg if the line was + * not already broken */ + diag2(0, "Line broken"); + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + break; + } + } /* end of switch */ + /* + * We must make this check, just in case there was an unexpected + * EOF. + */ + if (type_code != 0) { + /* + * The only intended purpose of calling lexi() below is to + * categorize the next token in order to decide whether to + * continue buffering forthcoming tokens. Once the buffering + * is over, lexi() will be called again elsewhere on all of + * the tokens - this time for normal processing. + * + * Calling it for this purpose is a bug, because lexi() also + * changes the parser state and discards leading whitespace, + * which is needed mostly for comment-related considerations. + * + * Work around the former problem by giving lexi() a copy of + * the current parser state and discard it if the call turned + * out to be just a look ahead. + * + * Work around the latter problem by copying all whitespace + * characters into the buffer so that the later lexi() call + * will read them. + */ + if (sc_end != NULL) { + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + *sc_end++ = *buf_ptr++; + if (sc_end >= &save_com[sc_size]) { + errx(1, "input too long"); + } + } + if (buf_ptr >= buf_end) { + fill_buffer(); + } + } + transient_state = ps; + type_code = lexi(&transient_state); /* read another token */ + if (type_code != newline && type_code != form_feed && + type_code != comment && !transient_state.search_brace) { + ps = transient_state; + } + } + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag2(1, "Stuff missing from end of file"); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + int len = e_com - s_com; + + CHECK_SIZE_CODE(len + 3); + *e_code++ = ' '; + memcpy(e_code, s_com, len); + e_code += len; + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE(3); /* maximum number of increments of e_code + * before the next CHECK_SIZE_CODE or + * dump_line() is 2. After that there's the + * final increment for the null character. */ + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + /* count parens to make Healy happy */ + if (++ps.p_l_follow == nitems(ps.paren_indents)) { + diag3(0, "Reached internal limit of %d unclosed parens", + nitems(ps.paren_indents)); + ps.p_l_follow--; + } + if (*token == '[') + /* not a function pointer declaration or a function call */; + else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* function pointer declarations */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank && + ((ps.last_token != ident && ps.last_token != funcname) || + /* offsetof (1) is never allowed a space; sizeof (2) gets + * one iff -bs; all other keywords (>2) always get a space + * before lparen */ + ps.keyword + Bill_Shannon > 2)) + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + /* + * parenthesized type following sizeof or offsetof is not a cast, + * and we assume the same for any other non-keyword identifier, + * to support macros that take types + */ + if (ps.last_token == ident && + (ps.keyword == 0 || ps.keyword == 1 || ps.keyword == 2)) + ps.not_cast_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + ps.want_blank = space_after_cast; + } else + ps.want_blank = true; + ps.not_cast_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag3(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* pointer declarations */ + + /* + * if this is a unary op in a declaration, we should indent + * this token + */ + for (i = 0; token[i]; ++i) + /* find length of token */; + indent_declaration(dec_ind - i, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank) + *e_code++ = ' '; + + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len); + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * <c>?<n>:<n> construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_or_st) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + /* + * turn everything so far into a label + */ + { + int len = e_code - s_code; + + CHECK_SIZE_LAB(len + 3); + memcpy(e_lab, s_code, len); + e_lab += len; + *e_lab++ = ':'; + *e_lab = '\0'; + e_code = s_code; + } + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + if (ps.dec_nest == 0) + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in an error */ + squest = 0; + if (ps.last_token == rparen) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.not_cast_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent stray semicolons in declarations */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for an if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after an end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + if (function_brace_split) { /* dump the line prior to the + * brace ... */ + dump_line(); + ps.want_blank = false; + } else /* add a space between the decl and brace */ + ps.want_blank = true; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceding unbalanced + * parens */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest] = dec_ind; + if (++ps.dec_nest == nitems(di_stack)) { + diag3(0, "Reached internal limit of %d struct levels", + nitems(di_stack)); + ps.dec_nest--; + } + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we can't be in the middle of + * a declaration, so don't do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + ps.in_decl = false; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag2(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case type_def: + case storage: + prefix_blankline_requested = 0; + goto copy_id; + + case structure: + if (ps.p_l_follow > 0) + goto copy_id; + /* FALLTHROUGH */ + case decl: /* we have a declaration type (int, etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + if (ps.ind_level == 0 || ps.dec_nest > 0) { + /* global variable or struct member in local variable */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); + } else { + /* local variable */ + dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; + tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); + } + goto copy_id; + + case funcname: + case ident: /* got an identifier or constant */ + if (ps.in_decl) { + if (type_code == funcname) { + ps.in_decl = false; + if (procnames_start_line && s_code != e_code) { + *e_code = '\0'; + dump_line(); + } + else if (ps.want_blank) { + *e_code++ = ' '; + } + ps.want_blank = false; + } + else if (!ps.block_init && !ps.dumped_decl_indent && + ps.paren_level == 0) { /* if we are in a declaration, we + * must indent identifier */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + ps.want_blank = false; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, s_token, len); + e_code += len; + } + if (type_code != funcname) + ps.want_blank = true; + break; + + case strpfx: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent leading commas and not the actual identifiers */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || + count_spaces_until(compute_code_target(), s_code, e_code) > + max_col - tabsize)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + CHECK_SIZE_LAB(1); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || (in_comment && !had_eof)) { + CHECK_SIZE_LAB(2); + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == NULL) { + /* comment on preprocessor line */ + if (sc_end == NULL) { /* if this is the first comment, + * we must set up the buffer */ + save_com = sc_buf; + sc_end = &save_com[0]; + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + if (sc_end - save_com + com_end - com_start > sc_size) + errx(1, "input too long"); + memmove(sc_end, s_lab + com_start, com_end - com_start); + sc_end += com_end - com_start; + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + } + CHECK_SIZE_LAB(1); + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */ + if ((size_t)ifdef_level < nitems(state_stack)) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag2(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */ + if (ifdef_level <= 0) + diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag2(1, "Unmatched #endif"); + else + ifdef_level--; + } else { + struct directives { + int size; + const char *string; + } + recognized[] = { + {7, "include"}, + {6, "define"}, + {5, "undef"}, + {4, "line"}, + {5, "error"}, + {6, "pragma"} + }; + int d = nitems(recognized); + while (--d >= 0) + if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0) + break; + if (d < 0) { + diag2(1, "Unrecognized cpp directive"); + break; + } + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + else { + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a / followed by * this is a biggie */ + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +static void +bakcopy(void) +{ + int n, + bakchn; + char buff[8 * 1024]; + const char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(1, "%s", bakfile); + while ((n = read(fileno(input), buff, sizeof(buff))) > 0) + if (write(bakchn, buff, n) != n) + err(1, "%s", bakfile); + if (n < 0) + err(1, "%s", in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == NULL) + err(1, "%s", bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == NULL) { + unlink(bakfile); + err(1, "%s", in_name); + } +} + +static void +indent_declaration(int cur_dec_ind, int tabs_to_var) +{ + int pos = e_code - s_code; + char *startpos = e_code; + + /* + * get the tab math right for indentations that are not multiples of tabsize + */ + if ((ps.ind_level * ps.ind_size) % tabsize != 0) { + pos += (ps.ind_level * ps.ind_size) % tabsize; + cur_dec_ind += (ps.ind_level * ps.ind_size) % tabsize; + } + if (tabs_to_var) { + int tpos; + + CHECK_SIZE_CODE(cur_dec_ind / tabsize); + while ((tpos = tabsize * (1 + pos / tabsize)) <= cur_dec_ind) { + *e_code++ = (!postgres_tab_rules || + tpos != pos + 1 || + cur_dec_ind >= tpos + tabsize) ? '\t' : ' '; + pos = tpos; + } + } + CHECK_SIZE_CODE(cur_dec_ind - pos + 1); + while (pos < cur_dec_ind) { + *e_code++ = ' '; + pos++; + } + if (e_code == startpos && ps.want_blank) { + *e_code++ = ' '; + ps.want_blank = false; + } +} diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h new file mode 100644 index 0000000000..1708dbc19f --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2001 Jens Schweikhardt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); +#endif + +#define nitems(array) (sizeof (array) / sizeof (array[0])) + +void add_typename(const char *); +void alloc_typenames(void); +int compute_code_target(void); +int compute_label_target(void); +int count_spaces(int, char *); +int count_spaces_until(int, char *, char *); +int lexi(struct parser_state *); +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); +void set_defaults(void); +void set_option(char *); +void set_profile(const char *); diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h new file mode 100644 index 0000000000..24c43fa420 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_codes.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_codes.h 309380 2016-12-02 01:25:51Z pfg $ + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 +#define strpfx 33 +#define storage 34 +#define funcname 35 +#define type_def 36 +#define structure 37 diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h new file mode 100644 index 0000000000..398784b3f4 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -0,0 +1,343 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_globs.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_globs.h 303735 2016-08-03 22:08:07Z pfg $ + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + + +#ifndef false +#define false 0 +#endif +#ifndef true +#define true 1 +#endif + +/* + * Exactly one calling file should define this symbol. The global variables + * will be defined in that file, and just referenced elsewhere. + */ +#ifdef DECLARE_INDENT_GLOBALS +#define extern +#endif + +extern FILE *input; /* the fid for the input file */ +extern FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE(desired_size) \ + if (e_code + (desired_size) >= l_code) { \ + int nsize = l_code-s_code + 400 + desired_size; \ + int code_len = e_code-s_code; \ + codebuf = (char *) realloc(codebuf, nsize); \ + if (codebuf == NULL) \ + err(1, NULL); \ + e_code = codebuf + code_len + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM(desired_size) \ + if (e_com + (desired_size) >= l_com) { \ + int nsize = l_com-s_com + 400 + desired_size; \ + int com_len = e_com - s_com; \ + int blank_pos; \ + if (last_bl != NULL) \ + blank_pos = last_bl - combuf; \ + else \ + blank_pos = -1; \ + combuf = (char *) realloc(combuf, nsize); \ + if (combuf == NULL) \ + err(1, NULL); \ + e_com = combuf + com_len + 1; \ + if (blank_pos > 0) \ + last_bl = combuf + blank_pos; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB(desired_size) \ + if (e_lab + (desired_size) >= l_lab) { \ + int nsize = l_lab-s_lab + 400 + desired_size; \ + int label_len = e_lab - s_lab; \ + labbuf = (char *) realloc(labbuf, nsize); \ + if (labbuf == NULL) \ + err(1, NULL); \ + e_lab = labbuf + label_len + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN(desired_size) \ + if (e_token + (desired_size) >= l_token) { \ + int nsize = l_token-s_token + 400 + desired_size; \ + int token_len = e_token - s_token; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + if (tokenbuf == NULL) \ + err(1, NULL); \ + e_token = tokenbuf + token_len + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +extern char *labbuf; /* buffer for label */ +extern char *s_lab; /* start ... */ +extern char *e_lab; /* .. and end of stored label */ +extern char *l_lab; /* limit of label buffer */ + +extern char *codebuf; /* buffer for code section */ +extern char *s_code; /* start ... */ +extern char *e_code; /* .. and end of stored code */ +extern char *l_code; /* limit of code section */ + +extern char *combuf; /* buffer for comments */ +extern char *s_com; /* start ... */ +extern char *e_com; /* ... and end of stored comments */ +extern char *l_com; /* limit of comment buffer */ + +#define token s_token +extern char *tokenbuf; /* the last token scanned */ +extern char *s_token; +extern char *e_token; +extern char *l_token; + +extern char *in_buffer; /* input buffer */ +extern char *in_buffer_limit; /* the end of the input buffer */ +extern char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +extern char *buf_end; /* ptr to first after last char in in_buffer */ + +extern char sc_buf[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +extern char *save_com; /* start of the comment stored in sc_buf */ +extern char *sc_end; /* pointer into save_com buffer */ + +extern char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +extern char *be_save; /* similarly saved value of buf_end */ + + +extern int found_err; +extern int blanklines_after_declarations; +extern int blanklines_before_blockcomments; +extern int blanklines_after_procs; +extern int blanklines_around_conditional_compilation; +extern int swallow_optional_blanklines; +extern int n_real_blanklines; +extern int prefix_blankline_requested; +extern int postfix_blankline_requested; +extern int break_comma; /* when true and not in parens, break after a + * comma */ +extern int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +extern float case_ind; /* indentation level to be used for a "case + * n:" */ +extern int code_lines; /* count of lines with code */ +extern int had_eof; /* set to true when input is exhausted */ +extern int line_no; /* the current line number. */ +extern int max_col; /* the maximum allowable line length */ +extern int verbose; /* when true, non-essential error messages are + * printed */ +extern int cuddle_else; /* true if else should cuddle up to '}' */ +extern int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +extern int comment_delimiter_on_blankline; +extern int troff; /* true iff were generating troff input */ +extern int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +extern int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +extern int format_block_comments; /* true if comments beginning with + * `/ * \n' are to be reformatted */ +extern int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +extern int inhibit_formatting; /* true if INDENT OFF is in effect */ +extern int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +extern int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +extern int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +extern int lineup_to_parens_always; /* if true, do not attempt to keep + * lined-up code within the margin */ +extern int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +extern int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +extern int block_comment_max_col; +extern int extra_expression_indent; /* true if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ +extern int function_brace_split; /* split function declaration and + * brace onto separate lines */ +extern int use_tabs; /* set true to use tabs for spacing, + * false uses all spaces */ +extern int auto_typedefs; /* set true to recognize identifiers + * ending in "_t" like typedefs */ +extern int space_after_cast; /* "b = (int) a" vs "b = (int)a" */ +extern int postgres_tab_rules; /* use Postgres tab-vs-space rules */ +extern int tabsize; /* the size of a tab */ +extern int else_endif_com_ind; /* the column in which comments to + * the right of #else and #endif + * should start */ + +extern int ifdef_level; + +struct parser_state { + int last_token; + int p_stack[256]; /* this is the parsers stack */ + int il[64]; /* this stack stores indentation levels */ + float cstk[32]; /* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in / followed by * */ + int comment_delta; /* used to set up indentation for all lines + * of a boxed comment after the first one */ + int n_comment_delta;/* remembers how many columns there were + * before the start of a box comment so that + * forthcoming lines of the comment are + * indented properly */ + int cast_mask; /* indicates which close parens potentially + * close off casts */ + int not_cast_mask; /* indicates which close parens definitely + * close off something else than casts */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * comment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within statements */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int local_decl_indent; /* like decl_indent but for locals */ + int keyword; /* the type of a keyword or 0 */ + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +}; + +extern struct parser_state ps; +extern struct parser_state state_stack[5]; +extern struct parser_state match_state[5]; + +/* Undo previous hackery */ +#ifdef DECLARE_INDENT_GLOBALS +#undef extern +#endif diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c new file mode 100644 index 0000000000..3ce8bfb70c --- /dev/null +++ b/src/tools/pg_bsd_indent/io.c @@ -0,0 +1,608 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +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 +dump_line(void) +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + int cur_col, + target_col = 1; + static int not_first_line; + + if (ps.procname[0]) { + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) { + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + *e_lab = '\0'; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + (int)(e_lab - s), s); + } + else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + int i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) { /* print comment, if any */ + int target = ps.com_col; + char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') /* consider original indentation in + * case this is a box comment */ + com_st++, target += tabsize; + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = tabsize * (1 + (target - 1) / tabsize) + 1, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment can't fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace((unsigned char)e_com[-1])) + e_com--; + (void)pad_output(cur_col, target); + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com = combuf + 1) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + if (ps.paren_level > 0) + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; +} + +int +compute_code_target(void) +{ + int target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent + * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level); + else if (lineup_to_parens_always) + target_col = paren_target; + else { + int w; + int t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int +compute_label_target(void) +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : 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 + * + * All rights reserved + * + * + * NAME: fill_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 + * buffer from temporary buffer + * + */ +void +fill_buffer(void) +{ /* this routine reads stuff from the input */ + char *p; + int i; + FILE *f = input; + + if (bp_save != NULL) { /* there is a partly filled input buffer left */ + 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 */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + int size = (in_buffer_limit - in_buffer) * 2 + 10; + int offset = p - in_buffer; + in_buffer = realloc(in_buffer, size); + if (in_buffer == NULL) + errx(1, "input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + 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; + } + buf_ptr = in_buffer; + buf_end = p; + if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') { + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + } + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column + * target integer The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +static int +pad_output(int current, int target) + /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + /* current: the current column value */ + /* target: position we want it at */ +{ + int curr; /* internal column pointer */ + + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + if (use_tabs) { + int tcur; + + while ((tcur = tabsize * (1 + (curr - 1) / tabsize) + 1) <= target) { + putc((!postgres_tab_rules || + tcur != curr + 1 || + target >= tcur + tabsize) ? '\t' : ' ', output); + curr = tcur; + } + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces_until(int cur, char *buffer, char *end) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ +{ + char *buf; /* used to look thru buffer */ + + for (buf = buffer; *buf != '\0' && buf != end; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = tabsize * (1 + (cur - 1) / tabsize) + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +int +count_spaces(int cur, char *buffer) +{ + return (count_spaces_until(cur, buffer, NULL)); +} + +void +diag4(int level, const char *msg, int a, int b) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void +diag3(int level, const char *msg, int a) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a); + fprintf(stderr, "\n"); + } +} + +void +diag2(int level, const char *msg) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, "%s", msg); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, "%s", msg); + fprintf(stderr, "\n"); + } +} + diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c new file mode 100644 index 0000000000..f01596a870 --- /dev/null +++ b/src/tools/pg_bsd_indent/lexi.c @@ -0,0 +1,724 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include <err.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +#define alphanum 1 +#ifdef undef +#define opchar 3 +#endif + +struct templ { + const char *rwd; + int rwcode; +}; + +/* + * This table has to be sorted alphabetically, because it'll be used in binary + * search. For the same reason, string must be the first thing in struct templ. + */ +struct templ specials[] = +{ + {"_Bool", 4}, + {"_Complex", 4}, + {"_Imaginary", 4}, + {"auto", 10}, + {"bool", 4}, + {"break", 9}, + {"case", 8}, + {"char", 4}, + {"complex", 4}, + {"const", 4}, + {"continue", 12}, + {"default", 8}, + {"do", 6}, + {"double", 4}, + {"else", 6}, + {"enum", 3}, + {"extern", 10}, + {"float", 4}, + {"for", 5}, + {"global", 4}, + {"goto", 9}, + {"if", 5}, + {"imaginary", 4}, + {"inline", 12}, + {"int", 4}, + {"long", 4}, + {"offsetof", 1}, + {"register", 10}, + {"restrict", 12}, + {"return", 9}, + {"short", 4}, + {"signed", 4}, + {"sizeof", 2}, + {"static", 10}, + {"struct", 3}, + {"switch", 7}, + {"typedef", 11}, + {"union", 3}, + {"unsigned", 4}, + {"void", 4}, + {"volatile", 4}, + {"while", 5} +}; + +const char **typenames; +int typename_count; +int typename_top = -1; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + +static int +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) +{ + int unary_delim; /* this is set to 1 if the current token + * forces a following operator to be unary */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + state->col_1 = state->last_nl; /* tell world that this token started + * in column 1 iff the last thing + * scanned was a newline */ + state->last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + state->col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr & 127] == alphanum || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + /* + * we have a character or number + */ + struct templ *p; + + if (isdigit((unsigned char)*buf_ptr) || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + int seendot = 0, + seenexp = 0, + seensfx = 0; + + /* + * base 2, base 8, base 16: + */ + if (buf_ptr[0] == '0' && buf_ptr[1] != '.') { + int len; + + if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B') + len = strspn(buf_ptr + 2, "01") + 2; + else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X') + len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2; + else + len = strspn(buf_ptr + 1, "012345678") + 1; + if (len > 0) { + CHECK_SIZE_TOKEN(len); + memcpy(e_token, buf_ptr, len); + e_token += len; + buf_ptr += len; + } + else + diag2(1, "Unterminated literal"); + } + else /* base 10: */ + while (1) { + if (*buf_ptr == '.') { + if (seendot) + break; + else + seendot++; + } + CHECK_SIZE_TOKEN(3); + *e_token++ = *buf_ptr++; + if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') { + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + } + + while (1) { + CHECK_SIZE_TOKEN(2); + if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) { + *e_token++ = *buf_ptr++; + seensfx |= 1; + continue; + } + if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) { + if (buf_ptr[1] == buf_ptr[0]) + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + seensfx |= 2; + continue; + } + break; + } + } + else + while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) { + /* fill_buffer() terminates buffer with newline */ + if (*buf_ptr == BACKSLASH) { + if (*(buf_ptr + 1) == '\n') { + buf_ptr += 2; + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; + } + CHECK_SIZE_TOKEN(1); + /* copy it over */ + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token = '\0'; + + if (s_token[0] == 'L' && s_token[1] == '\0' && + (*buf_ptr == '"' || *buf_ptr == '\'')) + return (strpfx); + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + state->keyword = 0; + if (state->last_token == structure && !state->p_l_follow) { + /* if last token was 'struct' and we're not + * in parentheses, then this token + * should be treated as a declaration */ + state->last_u_d = true; + return (decl); + } + /* + * Operator after identifier is binary unless last token was 'struct' + */ + state->last_u_d = (state->last_token == structure); + + p = bsearch(s_token, + specials, + sizeof(specials) / sizeof(specials[0]), + sizeof(specials[0]), + strcmp_type); + if (p == NULL) { /* not a special keyword... */ + char *u; + + /* ... so maybe a type_t or a typedef */ + if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) && + strcmp(u, "_t") == 0) || (typename_top >= 0 && + bsearch(s_token, typenames, typename_top + 1, + sizeof(typenames[0]), strcmp_type))) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + goto found_typename; + } + } else { /* we have a keyword */ + state->keyword = p->rwcode; + state->last_u_d = true; + switch (p->rwcode) { + case 7: /* it is a switch */ + return (swstmt); + case 8: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + /* FALLTHROUGH */ + case 4: /* one of the declaration keywords */ + found_typename: + if (state->p_l_follow) { + /* inside parens: cast, param list, offsetof or sizeof */ + state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask; + } + if (state->last_token == period || state->last_token == unary_op) { + state->keyword = 0; + break; + } + if (p != NULL && p->rwcode == 3) + return (structure); + if (state->p_l_follow) + break; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 10: /* storage class specifier */ + return (storage); + + case 11: /* typedef */ + return (type_def); + + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 && + state->in_parameter_declaration == 0 && state->block_init == 0) { + 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 + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + else if (!state->p_l_follow && !state->block_init && + !state->in_stmt && + ((*buf_ptr == '*' && buf_ptr[1] != '=') || + isalpha((unsigned char)*buf_ptr)) && + (state->last_token == semicolon || state->last_token == lbrace || + state->last_token == rbrace)) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + return decl; + } + if (state->last_token == decl) /* if this is a declared variable, + * then following sign is unary */ + state->last_u_d = true; /* will make "int a -1" work */ + return (ident); /* the ident is not in the list */ + } /* end of processing for alphanum character */ + + /* Scan a non-alphanumeric token */ + + CHECK_SIZE_TOKEN(3); /* things like "<<=" */ + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = state->last_u_d; + state->last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exhausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + do { /* copy the string */ + while (1) { /* move one character or [/<char>]<char> */ + if (*buf_ptr == '\n') { + diag2(1, "Unterminated literal"); + goto stop_lit; + } + CHECK_SIZE_TOKEN(2); + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = state->last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (state->in_or_st) state->block_init = 1; + */ + /* ? code = state->block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = state->block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = state->last_u_d; + state->last_nl = true; /* remember this so we can set 'state->col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (state->last_token == ident || state->last_token == rparen) { + code = (state->last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + unary_delim = false; + code = unary_op; + state->want_blank = false; + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (state->in_or_st) + state->block_init = 1; +#ifdef undef + if (chartype[*buf_ptr & 127] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + case '*': + unary_delim = true; + if (!state->last_u_d) { + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = binary_op; + break; + } + while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) { + if (*buf_ptr == '*') { + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + } + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = unary_op; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = state->last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + state->last_u_d = unary_delim; + CHECK_SIZE_TOKEN(1); + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +void +alloc_typenames(void) +{ + + typenames = (const char **)malloc(sizeof(typenames[0]) * + (typename_count = 16)); + if (typenames == NULL) + err(1, NULL); +} + +void +add_typename(const char *key) +{ + int comparison; + const char *copy; + + if (typename_top + 1 >= typename_count) { + typenames = realloc((void *)typenames, + sizeof(typenames[0]) * (typename_count *= 2)); + if (typenames == NULL) + err(1, NULL); + } + if (typename_top == -1) + typenames[++typename_top] = copy = strdup(key); + else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) { + /* take advantage of sorted input */ + if (comparison == 0) /* remove duplicates */ + return; + typenames[++typename_top] = copy = strdup(key); + } + else { + int p; + + for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++) + /* find place for the new key */; + if (comparison == 0) /* remove duplicates */ + return; + memmove(&typenames[p + 1], &typenames[p], + sizeof(typenames[0]) * (++typename_top - p)); + typenames[p] = copy = strdup(key); + } + + if (copy == NULL) + err(1, NULL); +} diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c new file mode 100644 index 0000000000..bf6b1697f9 --- /dev/null +++ b/src/tools/pg_bsd_indent/parse.c @@ -0,0 +1,342 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void reduce(void); + +void +parse(int tk) /* tk: the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + /* + * Note that the stack pointer here is decremented, effectively + * reducing "else if" to "if". This saves a lot of stack space + * in case of a long "if-else-if ... else-if" sequence. + */ + ps.i_l_follow = ps.il[ps.tos--]; + /* the rest is the same as for dolit and forstmt */ + /* FALLTHROUGH */ + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag2(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ + if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag2(1, "Statement nesting error"); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag2(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + if (ps.tos >= nitems(ps.p_stack) - 1) + errx(1, "Parser stack overflow"); + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * <stmt> <stmt> <stmtl> + * <stmtl> <stmt> <stmtl> + * do <stmt> "dostmt" + * if <stmt> "ifstmt" + * switch <stmt> <stmt> + * decl <stmt> <stmt> + * "ifelse" <stmt> <stmt> + * for <stmt> <stmt> + * while <stmt> <stmt> + * "dostmt" while <stmt> + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +static void +reduce(void) +{ + int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* <do> <stmt> */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* <if> <stmt> */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* <switch> <stmt> */ + case_ind = ps.cstk[ps.tos - 1]; + /* FALLTHROUGH */ + case decl: /* finish of a declaration */ + case elsehead: + /* <<if> <stmt> else> <stmt> */ + case forstmt: + /* <for> <stmt> */ + case whilestmt: + /* <while> <stmt> */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* <anything else> <stmt> */ + return; + + } /* end of section for <stmt> on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.tos -= 2; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c new file mode 100644 index 0000000000..b0eacac1bb --- /dev/null +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + +void +pr_comment(void) +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = NULL; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + break_delim = false; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*' || + (*buf_ptr == '\n' && !format_block_comments)) { + ps.box_com = true; /* A comment with a '-' or '*' immediately + * after the /+* is assumed to be a boxed + * comment. A comment with a newline + * immediately after the /+* is assumed to + * be a block comment and is treated as a + * box comment unless format_block_comments + * is nonzero (the default). */ + break_delim = false; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + int target_col; + break_delim = false; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + if (s_lab != e_lab && s_lab[1] == 'e' && + (strncmp(s_lab, "#endif", 6) == 0 || + strncmp(s_lab, "#else", 5) == 0)) + ps.com_col = else_endif_com_ind <= target_col + ? target_col + 1 : else_endif_com_ind; + else + ps.com_col = ps.decl_on_line || ps.ind_level == 0 + ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col <= target_col) + ps.com_col = tabsize * (1 + (target_col - 1) / tabsize) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + /* + * Find out how much indentation there was originally, because that + * much will have to be ignored by pad_output() in dump_line(). This + * is a box comment, so nothing changes -- not even indentation. + * + * The comment we're about to read usually comes from in_buffer, + * unless it has been copied into save_com. + */ + char *start; + + start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? + sc_buf : in_buffer; + ps.n_comment_delta = 1 - count_spaces_until(1, start, buf_ptr - 2); + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/' followed by '*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + /* + * Don't put a break delimiter if this is a one-liner that won't wrap. + */ + if (break_delim) + for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) { + if (t_ptr >= buf_end) + fill_buffer(); + if (t_ptr[0] == '*' && t_ptr[1] == '/') { + if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2)) + break_delim = false; + break; + } + } + + if (break_delim) { + char *t = e_com; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments && ps.last_token != lbrace) + prefix_blankline_requested = 1; + dump_line(); + e_com = s_com = t; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + CHECK_SIZE_COM(3); + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = NULL; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t') + ; + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + dump_line(); + return; + } + last_bl = NULL; + CHECK_SIZE_COM(4); + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) + *e_com++ = ' '; + if (!ps.box_com && e_com - s_com > 3) { + dump_line(); + if (star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + else { + ps.last_nl = 1; + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + *e_com++ = ' '; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + CHECK_SIZE_COM(4); + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + if (break_delim) { + if (e_com > s_com + 3) { + dump_line(); + } + else + s_com = e_com; + *e_com++ = ' '; + } + if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com) + *e_com++ = ' '; /* ensure blank before end */ + *e_com++ = '*', *e_com++ = '/', *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else /* handle isolated '*' */ + *e_com++ = '*'; + break; + default: /* we have a random char */ + now_col = count_spaces_until(ps.com_col, s_com, e_com); + do { + CHECK_SIZE_COM(1); + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; /* remember we saw a blank */ + ++e_com; + now_col++; + } while (!memchr("*\n\r\b\t", *buf_ptr, 6) && + (now_col <= adj_max_col || !last_bl)); + ps.last_nl = false; + if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (last_bl == NULL) { + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + break; + } + *e_com = '\0'; + e_com = last_bl; + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t'; + t_ptr++) + ; + last_bl = NULL; + /* + * t_ptr will be somewhere between e_com (dump_line() reset) + * and l_com. So it's safe to copy byte by byte from t_ptr + * to e_com without any CHECK_SIZE_COM(). + */ + while (*t_ptr != '\0') { + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + break; + } + } +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0 b/src/tools/pg_bsd_indent/tests/binary.0 new file mode 100644 index 0000000000..0c5ebf7e8f --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0 @@ -0,0 +1,9 @@ +#define b00101010 -1 +void t(void) { + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0.stdout b/src/tools/pg_bsd_indent/tests/binary.0.stdout new file mode 100644 index 0000000000..6118ac5055 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0.stdout @@ -0,0 +1,11 @@ +#define b00101010 -1 +void +t(void) +{ + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0 b/src/tools/pg_bsd_indent/tests/comments.0 new file mode 100644 index 0000000000..7b65c2eb55 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0 @@ -0,0 +1,52 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void t(void) { + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on the next line. + * + * *test* + */ + + /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */ + + /* r309343 */ +} + +int c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0.stdout b/src/tools/pg_bsd_indent/tests/comments.0.stdout new file mode 100644 index 0000000000..8ca5aa518c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0.stdout @@ -0,0 +1,60 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void +t(void) +{ + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj + * kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on + * the next line. + * + * *test* + */ + + /* + * r309219 Go through linked list, freeing from the malloced (t[-1]) + * address. + */ + + /* r309343 */ +} + +int +c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.pro b/src/tools/pg_bsd_indent/tests/comments.pro new file mode 100644 index 0000000000..0959711b3d --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.pro @@ -0,0 +1 @@ +-bbb \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0 b/src/tools/pg_bsd_indent/tests/cppelsecom.0 new file mode 100644 index 0000000000..79aed65115 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0 @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout new file mode 100644 index 0000000000..047fc3d951 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/declarations.0 b/src/tools/pg_bsd_indent/tests/declarations.0 new file mode 100644 index 0000000000..8419494989 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0 @@ -0,0 +1,79 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct +{ + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex +{ + double x; + double y; +} Complex; + +void +t1 (char *a, int b, + void (*fn)(void)) +{} + +void t2 (char *x, int y) +{ + int a, + b, + c; + int + *d, + *e, + *f; + int (*g)(), + (*h)(), + (*i)(); + int j, + k, + l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int *int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( +struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/declarations.0.stdout b/src/tools/pg_bsd_indent/tests/declarations.0.stdout new file mode 100644 index 0000000000..ab5a447a8b --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0.stdout @@ -0,0 +1,73 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct { + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex { + double x; + double y; +} Complex; + +void +t1(char *a, int b, + void (*fn) (void)) +{ +} + +void +t2(char *x, int y) +{ + int a, b, c; + int + *d, *e, *f; + int (*g) (), (*h) (), (*i) (); + int j, k, l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], + x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int * +int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( + struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0 b/src/tools/pg_bsd_indent/tests/elsecomment.0 new file mode 100644 index 0000000000..61066c22b5 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0 @@ -0,0 +1,42 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void t(void) { + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ int a; else /* b */ int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) { + int a; + } + + + else if (0) { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout new file mode 100644 index 0000000000..7de23be089 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout @@ -0,0 +1,47 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void +t(void) +{ + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) + { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) + { + int a; + } else if (0) + { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.pro b/src/tools/pg_bsd_indent/tests/elsecomment.pro new file mode 100644 index 0000000000..115c4768e7 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.pro @@ -0,0 +1 @@ +-bl \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/enum.0 b/src/tools/pg_bsd_indent/tests/enum.0 new file mode 100644 index 0000000000..15057dc464 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0 @@ -0,0 +1,6 @@ +typedef enum +{ +PREWARM_PREFETCH, /* comment */ +PREWARM_READ, /* more comment */ +PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/enum.0.stdout b/src/tools/pg_bsd_indent/tests/enum.0.stdout new file mode 100644 index 0000000000..fd4653b854 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0.stdout @@ -0,0 +1,5 @@ +typedef enum { + PREWARM_PREFETCH, /* comment */ + PREWARM_READ, /* more comment */ + PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0 b/src/tools/pg_bsd_indent/tests/f_decls.0 new file mode 100644 index 0000000000..aeef03b704 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0 @@ -0,0 +1,27 @@ +char * x(void) +{ + type identifier; + type *pointer; + unused * value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) { + +} + +int +z(void) { + +} + +int x; +int *y; +int * * * * z; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0.stdout b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout new file mode 100644 index 0000000000..bc21248552 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout @@ -0,0 +1,30 @@ +char * +x(void) +{ + type identifier; + type *pointer; + unused *value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) +{ + +} + +int +z(void) +{ + +} + +int x; +int *y; +int ****z; diff --git a/src/tools/pg_bsd_indent/tests/float.0 b/src/tools/pg_bsd_indent/tests/float.0 new file mode 100644 index 0000000000..91f017fc1c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void t(void) { + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/float.0.stdout b/src/tools/pg_bsd_indent/tests/float.0.stdout new file mode 100644 index 0000000000..0f213182ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0.stdout @@ -0,0 +1,8 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void +t(void) +{ + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0 b/src/tools/pg_bsd_indent/tests/label.0 new file mode 100644 index 0000000000..7798a4d5c2 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0 @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void t(void) { + switch (1) + { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0.stdout b/src/tools/pg_bsd_indent/tests/label.0.stdout new file mode 100644 index 0000000000..22ec12272a --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0.stdout @@ -0,0 +1,14 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void +t(void) +{ + switch (1) { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.pro b/src/tools/pg_bsd_indent/tests/label.pro new file mode 100644 index 0000000000..75d1fe1a12 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.pro @@ -0,0 +1 @@ +-nut \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/list_head.0 b/src/tools/pg_bsd_indent/tests/list_head.0 new file mode 100644 index 0000000000..35874ebc4e --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0 @@ -0,0 +1,15 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; + + diff --git a/src/tools/pg_bsd_indent/tests/list_head.0.stdout b/src/tools/pg_bsd_indent/tests/list_head.0.stdout new file mode 100644 index 0000000000..2ebcca5730 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0.stdout @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; diff --git a/src/tools/pg_bsd_indent/tests/nsac.0 b/src/tools/pg_bsd_indent/tests/nsac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.0.stdout b/src/tools/pg_bsd_indent/tests/nsac.0.stdout new file mode 100644 index 0000000000..78f3b28757 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double)8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.pro b/src/tools/pg_bsd_indent/tests/nsac.pro new file mode 100644 index 0000000000..6bcbd2b1ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.pro @@ -0,0 +1 @@ +-nsac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0 b/src/tools/pg_bsd_indent/tests/offsetof.0 new file mode 100644 index 0000000000..078db19c29 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0 @@ -0,0 +1,5 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void t(void) { + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0.stdout b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout new file mode 100644 index 0000000000..199bf0fa07 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout @@ -0,0 +1,7 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void +t(void) +{ + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0 b/src/tools/pg_bsd_indent/tests/parens.0 new file mode 100644 index 0000000000..366536ce82 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0 @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) + { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0.stdout b/src/tools/pg_bsd_indent/tests/parens.0.stdout new file mode 100644 index 0000000000..2258f8d2f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0.stdout @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void +similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.pro b/src/tools/pg_bsd_indent/tests/parens.pro new file mode 100644 index 0000000000..e860911a11 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.pro @@ -0,0 +1 @@ +-ts4 -i4 -di12 -Tallocfunc diff --git a/src/tools/pg_bsd_indent/tests/sac.0 b/src/tools/pg_bsd_indent/tests/sac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.0.stdout b/src/tools/pg_bsd_indent/tests/sac.0.stdout new file mode 100644 index 0000000000..1849b28337 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.pro b/src/tools/pg_bsd_indent/tests/sac.pro new file mode 100644 index 0000000000..2b21505c72 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.pro @@ -0,0 +1 @@ +-sac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/struct.0 b/src/tools/pg_bsd_indent/tests/struct.0 new file mode 100644 index 0000000000..83142bfb19 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0 @@ -0,0 +1,21 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + { D, E }, + { F, G } + }; +} + +void u(struct x a) { + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/struct.0.stdout b/src/tools/pg_bsd_indent/tests/struct.0.stdout new file mode 100644 index 0000000000..3861312865 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0.stdout @@ -0,0 +1,23 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + {D, E}, + {F, G} + }; +} + +void +u(struct x a) +{ + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0 b/src/tools/pg_bsd_indent/tests/surplusbad.0 new file mode 100644 index 0000000000..07d07026db --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0 @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout new file mode 100644 index 0000000000..b288970fb9 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.pro b/src/tools/pg_bsd_indent/tests/surplusbad.pro new file mode 100644 index 0000000000..e828c8191c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.pro @@ -0,0 +1 @@ +-bad \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0 b/src/tools/pg_bsd_indent/tests/types_from_file.0 new file mode 100644 index 0000000000..6efca24fe1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0 @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c *z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout new file mode 100644 index 0000000000..8776ca6ba8 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c * z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.list b/src/tools/pg_bsd_indent/tests/types_from_file.list new file mode 100644 index 0000000000..5f733616b1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.list @@ -0,0 +1,2 @@ +b +a \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.pro b/src/tools/pg_bsd_indent/tests/types_from_file.pro new file mode 100644 index 0000000000..39eb911980 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.pro @@ -0,0 +1 @@ +-Utypes_from_file.list \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/wchar.0 b/src/tools/pg_bsd_indent/tests/wchar.0 new file mode 100644 index 0000000000..9910e77857 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; diff --git a/src/tools/pg_bsd_indent/tests/wchar.0.stdout b/src/tools/pg_bsd_indent/tests/wchar.0.stdout new file mode 100644 index 0000000000..92774abfdd --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; -- 2.31.1 From da770680de94ba589cb29310f42f71c2373e81cf Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 14:08:57 -0500 Subject: [PATCH v3 2/4] Sync pg_bsd_indent's copyright notices with Postgres practice. To avoid confusion, make the copyright notices in these files match the 3-clause form of the BSD license, per the blanket policy update that UC Berkeley issued years ago. Discussion: https://postgr.es/m/20230123011002.fzcaa3krql3mqsfn@awork3.anarazel.de --- src/tools/pg_bsd_indent/README | 37 ++++++++++++++++++++++++++ src/tools/pg_bsd_indent/args.c | 6 +---- src/tools/pg_bsd_indent/indent.c | 6 +---- src/tools/pg_bsd_indent/indent_codes.h | 6 +---- src/tools/pg_bsd_indent/indent_globs.h | 6 +---- src/tools/pg_bsd_indent/io.c | 6 +---- src/tools/pg_bsd_indent/lexi.c | 6 +---- src/tools/pg_bsd_indent/parse.c | 6 +---- src/tools/pg_bsd_indent/pr_comment.c | 6 +---- 9 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 33d016db62..846855d318 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +The FreeBSD originals of the files in this directory bear the +"4-clause" version of the BSD license. We have removed the +"advertising" clauses, as per UC Berkeley's directive here: +ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change +which reads: + +July 22, 1999 + +To All Licensees, Distributors of Any Version of BSD: + +As you know, certain of the Berkeley Software Distribution ("BSD") source +code files require that further distributions of products containing all or +portions of the software, acknowledge within their advertising materials +that such products contain software developed by UC Berkeley and its +contributors. + +Specifically, the provision reads: + +" * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors." + +Effective immediately, licensees and distributors are no longer required to +include the acknowledgement within advertising materials. Accordingly, the +foregoing paragraph of those BSD Unix files containing it is hereby deleted +in its entirety. + +William Hoskins +Director, Office of Technology Licensing +University of California, Berkeley + +---------- + +What follows is the README file as maintained by FreeBSD indent. + +---------- $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index 1c83f57049..b18eab5d39 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index d3a0ecefe9..0024993844 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h index 24c43fa420..6576bef75d 100644 --- a/src/tools/pg_bsd_indent/indent_codes.h +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h index 398784b3f4..917961bd3d 100644 --- a/src/tools/pg_bsd_indent/indent_globs.h +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c index 3ce8bfb70c..4149424294 100644 --- a/src/tools/pg_bsd_indent/io.c +++ b/src/tools/pg_bsd_indent/io.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c index f01596a870..943bf7ce6b 100644 --- a/src/tools/pg_bsd_indent/lexi.c +++ b/src/tools/pg_bsd_indent/lexi.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c index bf6b1697f9..e707da639c 100644 --- a/src/tools/pg_bsd_indent/parse.c +++ b/src/tools/pg_bsd_indent/parse.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c index b0eacac1bb..a9572b39ff 100644 --- a/src/tools/pg_bsd_indent/pr_comment.c +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * -- 2.31.1 From 3d6bd52162c733bf68e702efae569a945a630e3d Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 18:38:14 -0500 Subject: [PATCH v3 3/4] Integrate pg_bsd_indent into our build/test infrastructure. Update the Makefile and build directions for in-tree build, and add Meson build infrastructure. Also convert the ad-hoc test target into a TAP test. Currently, the Make build system will not build pg_bsd_indent by default, while the Meson system will. Both will test it during "make check-world" or "ninja test". Neither will install it automatically. (We might change some of these decisions later.) Also fix a couple of portability nits noted during early testing. Also, exclude pg_bsd_indent from pgindent's purview; at least for now, we'll leave it formatted similarly to the FreeBSD original. Tom Lane and Andres Freund Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de --- GNUmakefile.in | 2 +- src/Makefile | 2 + src/meson.build | 2 + src/tools/pg_bsd_indent/.gitignore | 12 +--- src/tools/pg_bsd_indent/Makefile | 62 ++++++++++++------- src/tools/pg_bsd_indent/README | 37 +++++++++++ src/tools/pg_bsd_indent/README.pg_bsd_indent | 30 --------- src/tools/pg_bsd_indent/args.c | 2 +- src/tools/pg_bsd_indent/indent.c | 2 +- src/tools/pg_bsd_indent/indent.h | 2 +- src/tools/pg_bsd_indent/meson.build | 40 ++++++++++++ .../pg_bsd_indent/t/001_pg_bsd_indent.pl | 53 ++++++++++++++++ src/tools/pgindent/exclude_file_patterns | 4 ++ 13 files changed, 186 insertions(+), 64 deletions(-) delete mode 100644 src/tools/pg_bsd_indent/README.pg_bsd_indent create mode 100644 src/tools/pg_bsd_indent/meson.build create mode 100644 src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl diff --git a/GNUmakefile.in b/GNUmakefile.in index 5434467381..9c18c56233 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -68,7 +68,7 @@ check check-tests installcheck installcheck-parallel installcheck-tests: CHECKPR check check-tests installcheck installcheck-parallel installcheck-tests: submake-generated-headers $(MAKE) -C src/test/regress $@ -$(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin,check) +$(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin src/tools/pg_bsd_indent,check) $(call recurse,checkprep, src/test src/pl src/interfaces contrib src/bin) $(call recurse,installcheck-world,src/test src/pl src/interfaces contrib src/bin,installcheck) diff --git a/src/Makefile b/src/Makefile index 79e274a476..94649c36c7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -66,11 +66,13 @@ clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ distclean maintainer-clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ rm -f Makefile.port Makefile.global diff --git a/src/meson.build b/src/meson.build index 80fd2823a9..bceeca70f9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -13,6 +13,8 @@ subdir('pl') subdir('interfaces') +subdir('tools/pg_bsd_indent') + ### Generate a Makefile.global that's complete enough for PGXS to work. # diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore index 4c5d8dc691..b27e3610d5 100644 --- a/src/tools/pg_bsd_indent/.gitignore +++ b/src/tools/pg_bsd_indent/.gitignore @@ -1,10 +1,4 @@ -# Global excludes across all subdirectories -*.o -*.obj -*.exe - -# Local excludes in root directory /pg_bsd_indent -/*.out -/*.list -/tests.diff +# Generated by test suite +/log/ +/tmp_check/ diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index ee046f36f0..ee3d494f40 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -1,35 +1,55 @@ #------------------------------------------------------------------------- # -# Makefile for pg_bsd_indent +# src/tools/pg_bsd_indent/Makefile # -# Copyright (c) 2017, PostgreSQL Global Development Group +# Copyright (c) 2017-2023, PostgreSQL Global Development Group # #------------------------------------------------------------------------- PGFILEDESC = "pg_bsd_indent - indent C code nicely" PGAPPICON = win32 -PROGRAM = pg_bsd_indent -OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) +subdir = src/tools/pg_bsd_indent +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global -# clean junk left behind by "make test" -EXTRA_CLEAN = *.out *.list tests.diff +OBJS = \ + $(WIN32RES) \ + args.o \ + err.o \ + indent.o \ + io.o \ + lexi.o \ + parse.o \ + pr_comment.o -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) +all: pg_bsd_indent -# pgxs.mk assumes too much about what "make check" means, so call it "test" +pg_bsd_indent: $(OBJS) | submake-libpgport + $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pg_bsd_indent$(X) '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +clean distclean maintainer-clean: + rm -f pg_bsd_indent$(X) $(OBJS) + rm -rf log/ tmp_check/ + +check: + $(prove_check) + +installcheck: + $(prove_installcheck) + +# Provide this alternate test name to allow testing pg_bsd_indent +# without building all of the surrounding Postgres installation. .PHONY: test -test: $(PROGRAM) - @rm -f tests.diff - @cp $(srcdir)/tests/*.list . - @for testsrc in $(srcdir)/tests/*.0; do \ - test=`basename "$$testsrc" .0`; \ - ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ - diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ - done - @cat tests.diff - @test '!' -s tests.diff - @echo Tests complete. +test: pg_bsd_indent + $(prove_installcheck) diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 846855d318..992d4fce61 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +src/tools/pg_bsd_indent/README + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, configure the surrounding Postgres source tree, +then run "make" in this directory. +Optionally, run "make test" for some simple tests. + +You'll need to install pg_bsd_indent somewhere in your PATH before +using it. Most likely, if you're a developer, you don't want to +put it in the same place as where the surrounding Postgres build +gets installed. Therefore, do this part with something like + + make install prefix=/usr/local + +If you are using Meson to build, the standard build targets will +build pg_bsd_indent and also test it, but there is not currently +provision for installing it anywhere. Manually copy the built +executable from build/src/tools/pg_bsd_indent/pg_bsd_indent to +wherever you want to put it. + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) +We're not planning to re-indent to Postgres style, because that +would make it difficult to compare to the FreeBSD sources. + +---------- + The FreeBSD originals of the files in this directory bear the "4-clause" version of the BSD license. We have removed the "advertising" clauses, as per UC Berkeley's directive here: diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent deleted file mode 100644 index 85c3dcac1c..0000000000 --- a/src/tools/pg_bsd_indent/README.pg_bsd_indent +++ /dev/null @@ -1,30 +0,0 @@ -pg_bsd_indent - -This is a lightly modified version of the "indent" program maintained -by the FreeBSD project. The modifications are mostly to make it portable -to non-BSD-ish platforms, though we do have one formatting switch we -couldn't convince upstream to take. - -To build it, you will need a Postgres installation, version 9.5 or newer. -(Once built, the program doesn't depend on that installation.) - -To build, just say "make"; or if pg_config from your Postgres installation -isn't in your PATH, say - make PG_CONFIG=path/to/pg_config -Optionally, run "make test" for some simple sanity checks. - -To install, copy pg_bsd_indent to somewhere in your usual PATH. -(If you say "make install", it will try to put it in your Postgres -installation directory, which is most likely not what you want for -long-term use.) - -TODO: add build support and instructions for Windows - - -If you happen to be hacking upon the indent source code, the closest -approximation to the existing indentation style seems to be - - ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c - -although this has by no means been rigorously adhered to. -(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index b18eab5d39..d08b086a88 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -176,7 +176,7 @@ void set_profile(const char *profile_name) { FILE *f; - char fname[PATH_MAX]; + char fname[MAXPGPATH]; static char prof[] = ".indent.pro"; if (profile_name == NULL) diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index 0024993844..34205f2ead 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -60,7 +60,7 @@ const char *in_name = "Standard Input"; /* will always point to name of input * file */ const char *out_name = "Standard Output"; /* will always point to name * of output file */ -char bakfile[MAXPATHLEN] = ""; +char bakfile[MAXPGPATH] = ""; int main(int argc, char **argv) diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h index 1708dbc19f..d9fff8ccd6 100644 --- a/src/tools/pg_bsd_indent/indent.h +++ b/src/tools/pg_bsd_indent/indent.h @@ -28,7 +28,7 @@ __FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); #endif -#define nitems(array) (sizeof (array) / sizeof (array[0])) +#define nitems(x) (sizeof((x)) / sizeof((x)[0])) void add_typename(const char *); void alloc_typenames(void); diff --git a/src/tools/pg_bsd_indent/meson.build b/src/tools/pg_bsd_indent/meson.build new file mode 100644 index 0000000000..5545c097bf --- /dev/null +++ b/src/tools/pg_bsd_indent/meson.build @@ -0,0 +1,40 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +pg_bsd_indent_sources = files( + 'args.c', + 'err.c', + 'indent.c', + 'io.c', + 'lexi.c', + 'parse.c', + 'pr_comment.c', +) + +if host_system == 'windows' + pg_bsd_indent_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'pg_bsd_indent', + '--FILEDESC', 'pg_bsd_indent - indent C code nicely']) +endif + +pg_bsd_indent = executable('pg_bsd_indent', + pg_bsd_indent_sources, + dependencies: [frontend_code], + include_directories: include_directories('.'), + kwargs: default_bin_args + { + 'install': false, +# possibly at some point do this: +# 'install_dir': dir_pgxs / 'src/tools/pg_bsd_indent', + }, +) +bin_targets += pg_bsd_indent + +tests += { + 'name': 'pg_bsd_indent', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_pg_bsd_indent.pl', + ], + }, +} diff --git a/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl new file mode 100644 index 0000000000..b40b3fdbbf --- /dev/null +++ b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl @@ -0,0 +1,53 @@ +# pg_bsd_indent: some simple tests + +# The test cases come from FreeBSD upstream, but this test scaffolding is ours. +# Copyright (c) 2017-2023, PostgreSQL Global Development Group + +use strict; +use warnings; + +use Cwd qw(getcwd); +use File::Copy "cp"; +use File::Spec; + +use PostgreSQL::Test::Utils; +use Test::More; + +# We expect to be started in the source directory (even in a VPATH build); +# we want to run pg_bsd_indent in the tmp_check directory to reduce clutter. +# (Also, it's caller's responsibility that pg_bsd_indent be in the PATH.) +my $src_dir = getcwd; +chdir ${PostgreSQL::Test::Utils::tmp_check}; + +# Basic tests: pg_bsd_indent knows --version but not much else. +program_version_ok('pg_bsd_indent'); + +# Run pg_bsd_indent on pre-fab test cases. +# Any diffs in the generated files will be accumulated here. +my $diff_file = "tests.diff"; + +# Copy support files to current dir, so *.pro files don't need to know path. +while (my $file = glob("$src_dir/tests/*.list")) +{ + cp($file, ".") || die "cp $file failed: $!"; +} + +while (my $test_src = glob("$src_dir/tests/*.0")) +{ + # extract test basename + my ($volume, $directories, $test) = File::Spec->splitpath($test_src); + $test =~ s/\.0$//; + # run pg_bsd_indent + command_ok( + [ + 'pg_bsd_indent', $test_src, + "$test.out", "-P$src_dir/tests/$test.pro" + ], + "pg_bsd_indent succeeds on $test"); + # check result matches, adding any diff to $diff_file + my $result = run_log([ 'diff', '-upd', "$test_src.stdout", "$test.out" ], + '>>', $diff_file); + ok($result, "pg_bsd_indent output matches for $test"); +} + +done_testing(); diff --git a/src/tools/pgindent/exclude_file_patterns b/src/tools/pgindent/exclude_file_patterns index f5c8857e31..6405a00511 100644 --- a/src/tools/pgindent/exclude_file_patterns +++ b/src/tools/pgindent/exclude_file_patterns @@ -47,6 +47,10 @@ src/pl/plperl/ppport\.h$ src/pl/plperl/SPI\.c$ src/pl/plperl/Util\.c$ # +# pg_bsd_indent has its own, idiosyncratic indentation style. +# We'll stick to that to permit comparison with the FreeBSD upstream. +src/tools/pg_bsd_indent/.* +# # Exclude any temporary installations that may be in the tree. /tmp_check/ /tmp_install/ -- 2.31.1 From 2395910690a0d2ada0ca6df4fe8983e268811be9 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 19:28:26 -0500 Subject: [PATCH v3 4/4] Add missing test dependency. I'd supposed there was already such a dependency for 'check', but nope. Per cfbot. --- src/tools/pg_bsd_indent/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index ee3d494f40..b138bb8b12 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -41,7 +41,7 @@ clean distclean maintainer-clean: rm -f pg_bsd_indent$(X) $(OBJS) rm -rf log/ tmp_check/ -check: +check: pg_bsd_indent $(prove_check) installcheck: -- 2.31.1
Hi, On 2023-02-11 18:54:00 -0500, Tom Lane wrote: > I ended up converting the test infrastructure into a TAP test, > which kind of feels like overkill; but the Meson system doesn't > seem to provide any lower-overhead way to run a test. FWIW, The default way to indicate failures in a test is the exit code. Obviously that allows less detailed reporting, but other than that, it works (that's how we test pg_regress today). > Also, for now both build systems *will* run tests on it, > although I'm not sure if plugging it into "make check-world" > is enough to cause the cfbot to do so, and I'm pretty sure > that the buildfarm won't notice that. That's sufficient for cfbot, on the CI task still using autoconf. And for meson it'll also suffice. It actually already ran: https://cirrus-ci.com/build/5984572702195712 The windows test failure is a transient issue independent of the patch (something went wrong with image permissions). However the linux autoconf one isn't: https://api.cirrus-ci.com/v1/artifact/task/5482952532951040/log/src/tools/pg_bsd_indent/tmp_check/log/regress_log_001_pg_bsd_indent # Running: pg_bsd_indent --version Command 'pg_bsd_indent' not found in /tmp/cirrus-ci-build/tmp_install/usr/local/pgsql/bin, /tmp/cirrus-ci-build/src/tools/pg_bsd_indent,/usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin at /tmp/cirrus-ci-build/src/tools/pg_bsd_indent/../../../src/test/perl/PostgreSQL/Test/Utils.pmline 832. I guess there might be a missing dependency? PATH looks sufficient. > I'll let the cfbot loose on this, and if it runs the tests > successfully I plan to go ahead and push. We can resolve > the installation question later. We might want to back off > testing too once we're satisfied about portability. > (I left out the 0004 declaration-formatting patch for now, btw.) Makes sense. Greetings, Andres Freund
Andres Freund <andres@anarazel.de> writes: > # Running: pg_bsd_indent --version > Command 'pg_bsd_indent' not found in /tmp/cirrus-ci-build/tmp_install/usr/local/pgsql/bin, /tmp/cirrus-ci-build/src/tools/pg_bsd_indent,/usr/local/sbin, /usr/local/bin, /usr/sbin, /usr/bin, /sbin, /bin at /tmp/cirrus-ci-build/src/tools/pg_bsd_indent/../../../src/test/perl/PostgreSQL/Test/Utils.pmline 832. > I guess there might be a missing dependency? PATH looks sufficient. Yeah, I expected that "check" would have a dependency on "all", but apparently it doesn't (and I'd missed this because I had pg_bsd_indent installed elsewhere in my PATH :-(). New build running now. regards, tom lane
Hmmm ... ci autoconf build is now happy, but the Windows run complains that none of the output files match. I'm betting that this is a Windows-newline problem, since I now see that indent.c opens both the input and output files in default (text) mode. I'm inclined to change it to open the output file in binary mode while leaving the input in text, which should have the effect of stripping \r if it's present. regards, tom lane
I wrote: > Hmmm ... ci autoconf build is now happy, but the Windows run complains > that none of the output files match. I'm betting that this is a > Windows-newline problem, since I now see that indent.c opens both the > input and output files in default (text) mode. I'm inclined to > change it to open the output file in binary mode while leaving the > input in text, which should have the effect of stripping \r if it's > present. So let's see if that theory is correct at all ... regards, tom lane From 55d1373fb0f7df6745ef8c34274bc82cb84d15d0 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 14:06:36 -0500 Subject: [PATCH v4 1/5] Import pg_bsd_indent sources. This brings in an exact copy of the pg_bsd_indent repo as of commit d301442799cea44e5ccb04331afc537764ec77c5 (2020-12-28). Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de --- src/tools/pg_bsd_indent/.gitignore | 10 + src/tools/pg_bsd_indent/Makefile | 35 + src/tools/pg_bsd_indent/README | 100 ++ src/tools/pg_bsd_indent/README.pg_bsd_indent | 30 + src/tools/pg_bsd_indent/args.c | 354 +++++ src/tools/pg_bsd_indent/err.c | 67 + src/tools/pg_bsd_indent/err.h | 45 + src/tools/pg_bsd_indent/indent.1 | 618 ++++++++ src/tools/pg_bsd_indent/indent.c | 1279 +++++++++++++++++ src/tools/pg_bsd_indent/indent.h | 51 + src/tools/pg_bsd_indent/indent_codes.h | 75 + src/tools/pg_bsd_indent/indent_globs.h | 343 +++++ src/tools/pg_bsd_indent/io.c | 608 ++++++++ src/tools/pg_bsd_indent/lexi.c | 724 ++++++++++ src/tools/pg_bsd_indent/parse.c | 342 +++++ src/tools/pg_bsd_indent/pr_comment.c | 358 +++++ src/tools/pg_bsd_indent/tests/binary.0 | 9 + src/tools/pg_bsd_indent/tests/binary.0.stdout | 11 + src/tools/pg_bsd_indent/tests/comments.0 | 52 + .../pg_bsd_indent/tests/comments.0.stdout | 60 + src/tools/pg_bsd_indent/tests/comments.pro | 1 + src/tools/pg_bsd_indent/tests/cppelsecom.0 | 7 + .../pg_bsd_indent/tests/cppelsecom.0.stdout | 7 + src/tools/pg_bsd_indent/tests/declarations.0 | 79 + .../pg_bsd_indent/tests/declarations.0.stdout | 73 + src/tools/pg_bsd_indent/tests/elsecomment.0 | 42 + .../pg_bsd_indent/tests/elsecomment.0.stdout | 47 + src/tools/pg_bsd_indent/tests/elsecomment.pro | 1 + src/tools/pg_bsd_indent/tests/enum.0 | 6 + src/tools/pg_bsd_indent/tests/enum.0.stdout | 5 + src/tools/pg_bsd_indent/tests/f_decls.0 | 27 + .../pg_bsd_indent/tests/f_decls.0.stdout | 30 + src/tools/pg_bsd_indent/tests/float.0 | 6 + src/tools/pg_bsd_indent/tests/float.0.stdout | 8 + src/tools/pg_bsd_indent/tests/label.0 | 13 + src/tools/pg_bsd_indent/tests/label.0.stdout | 14 + src/tools/pg_bsd_indent/tests/label.pro | 1 + src/tools/pg_bsd_indent/tests/list_head.0 | 15 + .../pg_bsd_indent/tests/list_head.0.stdout | 13 + src/tools/pg_bsd_indent/tests/nsac.0 | 4 + src/tools/pg_bsd_indent/tests/nsac.0.stdout | 6 + src/tools/pg_bsd_indent/tests/nsac.pro | 1 + src/tools/pg_bsd_indent/tests/offsetof.0 | 5 + .../pg_bsd_indent/tests/offsetof.0.stdout | 7 + src/tools/pg_bsd_indent/tests/parens.0 | 26 + src/tools/pg_bsd_indent/tests/parens.0.stdout | 26 + src/tools/pg_bsd_indent/tests/parens.pro | 1 + src/tools/pg_bsd_indent/tests/sac.0 | 4 + src/tools/pg_bsd_indent/tests/sac.0.stdout | 6 + src/tools/pg_bsd_indent/tests/sac.pro | 1 + src/tools/pg_bsd_indent/tests/struct.0 | 21 + src/tools/pg_bsd_indent/tests/struct.0.stdout | 23 + src/tools/pg_bsd_indent/tests/surplusbad.0 | 9 + .../pg_bsd_indent/tests/surplusbad.0.stdout | 9 + src/tools/pg_bsd_indent/tests/surplusbad.pro | 1 + .../pg_bsd_indent/tests/types_from_file.0 | 3 + .../tests/types_from_file.0.stdout | 3 + .../pg_bsd_indent/tests/types_from_file.list | 2 + .../pg_bsd_indent/tests/types_from_file.pro | 1 + src/tools/pg_bsd_indent/tests/wchar.0 | 6 + src/tools/pg_bsd_indent/tests/wchar.0.stdout | 6 + 61 files changed, 5737 insertions(+) create mode 100644 src/tools/pg_bsd_indent/.gitignore create mode 100644 src/tools/pg_bsd_indent/Makefile create mode 100644 src/tools/pg_bsd_indent/README create mode 100644 src/tools/pg_bsd_indent/README.pg_bsd_indent create mode 100644 src/tools/pg_bsd_indent/args.c create mode 100644 src/tools/pg_bsd_indent/err.c create mode 100644 src/tools/pg_bsd_indent/err.h create mode 100644 src/tools/pg_bsd_indent/indent.1 create mode 100644 src/tools/pg_bsd_indent/indent.c create mode 100644 src/tools/pg_bsd_indent/indent.h create mode 100644 src/tools/pg_bsd_indent/indent_codes.h create mode 100644 src/tools/pg_bsd_indent/indent_globs.h create mode 100644 src/tools/pg_bsd_indent/io.c create mode 100644 src/tools/pg_bsd_indent/lexi.c create mode 100644 src/tools/pg_bsd_indent/parse.c create mode 100644 src/tools/pg_bsd_indent/pr_comment.c create mode 100644 src/tools/pg_bsd_indent/tests/binary.0 create mode 100644 src/tools/pg_bsd_indent/tests/binary.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/comments.0 create mode 100644 src/tools/pg_bsd_indent/tests/comments.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/comments.pro create mode 100644 src/tools/pg_bsd_indent/tests/cppelsecom.0 create mode 100644 src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/declarations.0 create mode 100644 src/tools/pg_bsd_indent/tests/declarations.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.0 create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/elsecomment.pro create mode 100644 src/tools/pg_bsd_indent/tests/enum.0 create mode 100644 src/tools/pg_bsd_indent/tests/enum.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/f_decls.0 create mode 100644 src/tools/pg_bsd_indent/tests/f_decls.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/float.0 create mode 100644 src/tools/pg_bsd_indent/tests/float.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/label.0 create mode 100644 src/tools/pg_bsd_indent/tests/label.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/label.pro create mode 100644 src/tools/pg_bsd_indent/tests/list_head.0 create mode 100644 src/tools/pg_bsd_indent/tests/list_head.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/nsac.0 create mode 100644 src/tools/pg_bsd_indent/tests/nsac.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/nsac.pro create mode 100644 src/tools/pg_bsd_indent/tests/offsetof.0 create mode 100644 src/tools/pg_bsd_indent/tests/offsetof.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/parens.0 create mode 100644 src/tools/pg_bsd_indent/tests/parens.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/parens.pro create mode 100644 src/tools/pg_bsd_indent/tests/sac.0 create mode 100644 src/tools/pg_bsd_indent/tests/sac.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/sac.pro create mode 100644 src/tools/pg_bsd_indent/tests/struct.0 create mode 100644 src/tools/pg_bsd_indent/tests/struct.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.0 create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/surplusbad.pro create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.0 create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.0.stdout create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.list create mode 100644 src/tools/pg_bsd_indent/tests/types_from_file.pro create mode 100644 src/tools/pg_bsd_indent/tests/wchar.0 create mode 100644 src/tools/pg_bsd_indent/tests/wchar.0.stdout diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore new file mode 100644 index 0000000000..4c5d8dc691 --- /dev/null +++ b/src/tools/pg_bsd_indent/.gitignore @@ -0,0 +1,10 @@ +# Global excludes across all subdirectories +*.o +*.obj +*.exe + +# Local excludes in root directory +/pg_bsd_indent +/*.out +/*.list +/tests.diff diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile new file mode 100644 index 0000000000..ee046f36f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/Makefile @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------- +# +# Makefile for pg_bsd_indent +# +# Copyright (c) 2017, PostgreSQL Global Development Group +# +#------------------------------------------------------------------------- + +PGFILEDESC = "pg_bsd_indent - indent C code nicely" +PGAPPICON = win32 + +PROGRAM = pg_bsd_indent +OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) + +# clean junk left behind by "make test" +EXTRA_CLEAN = *.out *.list tests.diff + +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) + +# pgxs.mk assumes too much about what "make check" means, so call it "test" +.PHONY: test + +test: $(PROGRAM) + @rm -f tests.diff + @cp $(srcdir)/tests/*.list . + @for testsrc in $(srcdir)/tests/*.0; do \ + test=`basename "$$testsrc" .0`; \ + ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ + diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ + done + @cat tests.diff + @test '!' -s tests.diff + @echo Tests complete. diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README new file mode 100644 index 0000000000..33d016db62 --- /dev/null +++ b/src/tools/pg_bsd_indent/README @@ -0,0 +1,100 @@ + + $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ + +This is the C indenter, it originally came from the University of Illinois +via some distribution tape for PDP-11 Unix. It has subsequently been +hacked upon by James Gosling @ CMU. It isn't very pretty, and really needs +to be completely redone, but it is probably the nicest C pretty printer +around. + +Further additions to provide "Kernel Normal Form" were contributed +by the folks at Sun Microsystems. + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +> From mnetor!yunexus!oz@uunet.UU.NET Wed Mar 9 15:30:55 1988 +> Date: Tue, 8 Mar 88 18:36:25 EST +> From: yunexus!oz@uunet.UU.NET (Ozan Yigit) +> To: bostic@okeeffe.berkeley.edu +> Cc: ccvaxa!willcox@uunet.UU.NET, jag@sun.com, rsalz@uunet.UU.NET +> In-Reply-To: Keith Bostic's message of Tue, 16 Feb 88 16:09:06 PST +> Subject: Re: Indent... + +Thank you for your response about indent. I was wrong in my original +observation (or mis-observation :-). UCB did keep the Illinois +copyright intact. + +The issue still is whether we can distribute indent, and if we can, which +version. David Willcox (the author) states that: + +| Several people have asked me on what basis I claim that indent is in +| the public domain. I knew I would be sorry I made that posting. +| +| Some history. Way back in 1976, the project I worked on at the +| University of Illinois Center for Advanced Computation had a huge +| battle about how to format C code. After about a week of fighting, I +| got disgusted and wrote a program, which I called indent, to reformat C +| code. It had a bunch of different options that would let you format +| the output the way you liked. In particular, all of the different +| formats being championed were supported. +| +| It was my first big C program. It was ugly. It wasn't designed, it +| just sort of grew. But it pretty much worked, and it stopped most of +| the fighting. +| +| As a matter of form, I included a University of Illinois Copyright +| notice. However, my understanding was that, since the work was done +| on an ARPA contract, it was in the public domain. +| +| Time passed. Some years later, indent showed up on one of the early +| emacs distributions. +| +| Later still, someone from UC Berkeley called the UofI and asked if +| indent was in the public domain. They wanted to include it in their +| UNIX distributions, along with the emacs stuff. I was no longer at the +| UofI, but Rob Kolstad, who was, asked me about it. I told him I didn't +| care if they used it, and since then it has been on the BSD distributions. +| +| Somewhere along the way, several other unnamed people have had their +| hands in it. It was converted to understand version 7 C. (The +| original was version 6.) It was converted from its original filter +| interface to its current "blow away the user's file" interface. +| The $HOME/.indent.pro file parsing was added. Some more formatting +| options were added. +| +| The source I have right now has two copyright notices. One is the +| original from the UofI. One is from Berkeley. +| +| I am not a lawyer, and I certainly do not understand copyright law. As +| far as I am concerned, the bulk of this program, everything covered by +| the UofI copyright, is in the public domain, and worth every penny. +| Berkeley's copyright probably should only cover their changes, and I +| don't know their feelings about sending it out. + +In any case, there appears to be none at UofI to clarify/and change +that copyright, but I am confident (based on the statements of its +author) that the code, as it stands with its copyright, is +distributable, and will not cause any legal problems. + +Hence, the issue reduces to *which* one to distribute through +comp.sources.unix. I would suggest that with the permission of you +folks (given that you have parts copyrighted), we distribute the 4.3 +version of indent, which appears to be the most up-to-date version. I +happen to have just about every known version of indent, including the +very original submission from the author to a unix tape, later the +G-Emacs version, any 4.n version, sun version and the Unipress +version. I still think we should not have to "go-back-in-time" and +re-do all the work you people have done. + +I hope to hear from you as to what you think about this. You may of +course send 4.3 version to the moderator directly, or you can let me +know of your permission, and I will send the sources, or you can let +me know that 4.3 version is off-limits, in which case we would probably +have to revert to an older version. One way or another, I hope to get +a version of indent to comp.sources.unix. + +regards.. oz + +cc: ccvaxa!willcox + sun.com!jar + uunet!rsalz + diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent new file mode 100644 index 0000000000..85c3dcac1c --- /dev/null +++ b/src/tools/pg_bsd_indent/README.pg_bsd_indent @@ -0,0 +1,30 @@ +pg_bsd_indent + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, you will need a Postgres installation, version 9.5 or newer. +(Once built, the program doesn't depend on that installation.) + +To build, just say "make"; or if pg_config from your Postgres installation +isn't in your PATH, say + make PG_CONFIG=path/to/pg_config +Optionally, run "make test" for some simple sanity checks. + +To install, copy pg_bsd_indent to somewhere in your usual PATH. +(If you say "make install", it will try to put it in your Postgres +installation directory, which is most likely not what you want for +long-term use.) + +TODO: add build support and instructions for Windows + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c new file mode 100644 index 0000000000..1c83f57049 --- /dev/null +++ b/src/tools/pg_bsd_indent/args.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)args.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Argument scanning and profile reading code. Default parameters are set + * here as well. + */ + +#include <ctype.h> +#include <err.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +#define INDENT_VERSION "2.1.1" + +/* profile types */ +#define PRO_SPECIAL 1 /* special case */ +#define PRO_BOOL 2 /* boolean */ +#define PRO_INT 3 /* integer */ + +/* profile specials for booleans */ +#define ON 1 /* turn it on */ +#define OFF 0 /* turn it off */ + +/* profile specials for specials */ +#define IGN 1 /* ignore it */ +#define CLI 2 /* case label indent (float) */ +#define STDIN 3 /* use stdin */ +#define KEY 4 /* type (keyword) */ + +static void scan_profile(FILE *); + +#define KEY_FILE 5 /* only used for args */ +#define VERSION 6 /* only used for args */ + +const char *option_source = "?"; + +void add_typedefs_from_file(const char *str); + +/* + * N.B.: because of the way the table here is scanned, options whose names are + * substrings of other options must occur later; that is, with -lp vs -l, -lp + * must be first. Also, while (most) booleans occur more than once, the last + * default value is the one actually assigned. + */ +struct pro { + const char *p_name; /* name, e.g. -bl, -cli */ + int p_type; /* type (int, bool, special) */ + int p_default; /* the default value (if int) */ + int p_special; /* depends on type */ + int *p_obj; /* the associated variable */ +} pro[] = { + + {"T", PRO_SPECIAL, 0, KEY, 0}, + {"U", PRO_SPECIAL, 0, KEY_FILE, 0}, + {"-version", PRO_SPECIAL, 0, VERSION, 0}, + {"P", PRO_SPECIAL, 0, IGN, 0}, + {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation}, + {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop}, + {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations}, + {"bap", PRO_BOOL, false, ON, &blanklines_after_procs}, + {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments}, + {"bc", PRO_BOOL, true, OFF, &ps.leave_comma}, + {"bl", PRO_BOOL, true, OFF, &btype_2}, + {"br", PRO_BOOL, true, ON, &btype_2}, + {"bs", PRO_BOOL, false, ON, &Bill_Shannon}, + {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline}, + {"cd", PRO_INT, 0, 0, &ps.decl_com_ind}, + {"ce", PRO_BOOL, true, ON, &cuddle_else}, + {"ci", PRO_INT, 0, 0, &continuation_indent}, + {"cli", PRO_SPECIAL, 0, CLI, 0}, + {"cp", PRO_INT, 0, 0, &else_endif_com_ind}, + {"c", PRO_INT, 33, 0, &ps.com_ind}, + {"di", PRO_INT, 16, 0, &ps.decl_indent}, + {"dj", PRO_BOOL, false, ON, &ps.ljust_decl}, + {"d", PRO_INT, 0, 0, &ps.unindent_displace}, + {"eei", PRO_BOOL, false, ON, &extra_expression_indent}, + {"ei", PRO_BOOL, true, ON, &ps.else_if}, + {"fbs", PRO_BOOL, true, ON, &function_brace_split}, + {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, + {"fcb", PRO_BOOL, true, ON, &format_block_comments}, + {"ip", PRO_BOOL, true, ON, &ps.indent_parameters}, + {"i", PRO_INT, 8, 0, &ps.ind_size}, + {"lc", PRO_INT, 0, 0, &block_comment_max_col}, + {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent}, + {"lpl", PRO_BOOL, false, ON, &lineup_to_parens_always}, + {"lp", PRO_BOOL, true, ON, &lineup_to_parens}, + {"l", PRO_INT, 78, 0, &max_col}, + {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation}, + {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop}, + {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations}, + {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs}, + {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments}, + {"nbc", PRO_BOOL, true, ON, &ps.leave_comma}, + {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon}, + {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline}, + {"nce", PRO_BOOL, true, OFF, &cuddle_else}, + {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl}, + {"neei", PRO_BOOL, false, OFF, &extra_expression_indent}, + {"nei", PRO_BOOL, true, OFF, &ps.else_if}, + {"nfbs", PRO_BOOL, true, OFF, &function_brace_split}, + {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments}, + {"nfcb", PRO_BOOL, true, OFF, &format_block_comments}, + {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters}, + {"nlpl", PRO_BOOL, false, OFF, &lineup_to_parens_always}, + {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens}, + {"npcs", PRO_BOOL, false, OFF, &proc_calls_space}, + {"npro", PRO_SPECIAL, 0, IGN, 0}, + {"npsl", PRO_BOOL, true, OFF, &procnames_start_line}, + {"nsac", PRO_BOOL, false, OFF, &space_after_cast}, + {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, + {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, + {"ntpg", PRO_BOOL, false, OFF, &postgres_tab_rules}, + {"nut", PRO_BOOL, true, OFF, &use_tabs}, + {"nv", PRO_BOOL, false, OFF, &verbose}, + {"pcs", PRO_BOOL, false, ON, &proc_calls_space}, + {"psl", PRO_BOOL, true, ON, &procnames_start_line}, + {"sac", PRO_BOOL, false, ON, &space_after_cast}, + {"sc", PRO_BOOL, true, ON, &star_comment_cont}, + {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines}, + {"st", PRO_SPECIAL, 0, STDIN, 0}, + {"ta", PRO_BOOL, false, ON, &auto_typedefs}, + {"tpg", PRO_BOOL, false, ON, &postgres_tab_rules}, + {"ts", PRO_INT, 8, 0, &tabsize}, + {"ut", PRO_BOOL, true, ON, &use_tabs}, + {"v", PRO_BOOL, false, ON, &verbose}, + /* whew! */ + {0, 0, 0, 0, 0} +}; + +/* + * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments + * given in these files. + */ +void +set_profile(const char *profile_name) +{ + FILE *f; + char fname[PATH_MAX]; + static char prof[] = ".indent.pro"; + + if (profile_name == NULL) + snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); + else + snprintf(fname, sizeof(fname), "%s", profile_name + 2); + if ((f = fopen(option_source = fname, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + if ((f = fopen(option_source = prof, "r")) != NULL) { + scan_profile(f); + (void) fclose(f); + } + option_source = "Command line"; +} + +static void +scan_profile(FILE *f) +{ + int comment, i; + char *p; + char buf[BUFSIZ]; + + while (1) { + p = buf; + comment = 0; + while ((i = getc(f)) != EOF) { + if (i == '*' && !comment && p > buf && p[-1] == '/') { + comment = p - buf; + *p++ = i; + } else if (i == '/' && comment && p > buf && p[-1] == '*') { + p = buf + comment - 1; + comment = 0; + } else if (isspace((unsigned char)i)) { + if (p > buf && !comment) + break; + } else { + *p++ = i; + } + } + if (p != buf) { + *p++ = 0; + if (verbose) + printf("profile: %s\n", buf); + set_option(buf); + } + else if (i == EOF) + return; + } +} + +static const char * +eqin(const char *s1, const char *s2) +{ + while (*s1) { + if (*s1++ != *s2++) + return (NULL); + } + return (s2); +} + +/* + * Set the defaults. + */ +void +set_defaults(void) +{ + struct pro *p; + + /* + * Because ps.case_indent is a float, we can't initialize it from the + * table: + */ + ps.case_indent = 0.0; /* -cli0.0 */ + for (p = pro; p->p_name; p++) + if (p->p_type != PRO_SPECIAL) + *p->p_obj = p->p_default; +} + +void +set_option(char *arg) +{ + struct pro *p; + const char *param_start; + + arg++; /* ignore leading "-" */ + for (p = pro; p->p_name; p++) + if (*p->p_name == *arg && (param_start = eqin(p->p_name, arg)) != NULL) + goto found; + errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1); +found: + switch (p->p_type) { + + case PRO_SPECIAL: + switch (p->p_special) { + + case IGN: + break; + + case CLI: + if (*param_start == 0) + goto need_param; + ps.case_indent = atof(param_start); + break; + + case STDIN: + if (input == NULL) + input = stdin; + if (output == NULL) + output = stdout; + break; + + case KEY: + if (*param_start == 0) + goto need_param; + add_typename(param_start); + break; + + case KEY_FILE: + if (*param_start == 0) + goto need_param; + add_typedefs_from_file(param_start); + break; + + case VERSION: + printf("pg_bsd_indent %s (based on FreeBSD indent)\n", INDENT_VERSION); + exit(0); + + default: + errx(1, "set_option: internal error: p_special %d", p->p_special); + } + break; + + case PRO_BOOL: + if (p->p_special == OFF) + *p->p_obj = false; + else + *p->p_obj = true; + break; + + case PRO_INT: + if (!isdigit((unsigned char)*param_start)) { + need_param: + errx(1, "%s: ``%s'' requires a parameter", option_source, p->p_name); + } + *p->p_obj = atoi(param_start); + break; + + default: + errx(1, "set_option: internal error: p_type %d", p->p_type); + } +} + +void +add_typedefs_from_file(const char *str) +{ + FILE *file; + char line[BUFSIZ]; + + if ((file = fopen(str, "r")) == NULL) { + fprintf(stderr, "indent: cannot open file %s\n", str); + exit(1); + } + while ((fgets(line, BUFSIZ, file)) != NULL) { + /* Remove trailing whitespace */ + line[strcspn(line, " \t\n\r")] = '\0'; + add_typename(line); + } + fclose(file); +} diff --git a/src/tools/pg_bsd_indent/err.c b/src/tools/pg_bsd_indent/err.c new file mode 100644 index 0000000000..807319334b --- /dev/null +++ b/src/tools/pg_bsd_indent/err.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This is cut down to just the minimum that we need to build indent. + */ +#include "c.h" + +#include <err.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void +err(int eval, const char *fmt, ...) +{ + int code = errno; + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, ": "); + } + fprintf(stderr, "%s\n", strerror(code)); + va_end(ap); + exit(eval); +} + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (fmt != NULL) + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(eval); +} diff --git a/src/tools/pg_bsd_indent/err.h b/src/tools/pg_bsd_indent/err.h new file mode 100644 index 0000000000..a3e8f97825 --- /dev/null +++ b/src/tools/pg_bsd_indent/err.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + * $FreeBSD: stable/11/include/err.h 203964 2010-02-16 19:39:50Z imp $ + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * This is cut down to just the minimum that we need to build indent. + */ + +void err(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); +void errx(int, const char *, ...) + pg_attribute_noreturn() pg_attribute_printf(2, 3); + +#endif /* !_ERR_H_ */ diff --git a/src/tools/pg_bsd_indent/indent.1 b/src/tools/pg_bsd_indent/indent.1 new file mode 100644 index 0000000000..131abfe70b --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.1 @@ -0,0 +1,618 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 1976 Board of Trustees of the University of Illinois. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)indent.1 8.1 (Berkeley) 7/1/93 +.\" $FreeBSD: head/usr.bin/indent/indent.1 309524 2016-12-04 03:10:25Z pfg $ +.\" +.Dd December 2, 2016 +.Dt INDENT 1 +.Os +.Sh NAME +.Nm indent +.Nd indent and format C program source +.Sh SYNOPSIS +.Nm +.Op Ar input-file Op Ar output-file +.Op Fl bacc | Fl nbacc +.Op Fl bad | Fl nbad +.Op Fl badp | Fl nbadp +.Op Fl bap | Fl nbap +.Op Fl bbb | Fl nbbb +.Op Fl \&bc | Fl nbc +.Op Fl \&bl | Fl \&br +.Op Fl bs | Fl nbs +.Op Fl c Ns Ar n +.Op Fl cp Ns Ar n +.Op Fl \&cd Ns Ar n +.Bk -words +.Op Fl cdb | Fl ncdb +.Ek +.Op Fl \&ce | Fl nce +.Op Fl \&ci Ns Ar n +.Op Fl cli Ns Ar n +.Op Fl d Ns Ar n +.Op Fl \&di Ns Ar n +.Op Fl dj | Fl ndj +.Bk -words +.Op Fl ei | Fl nei +.Op Fl eei | Fl neei +.Ek +.Bk -words +.Op Fl fbs | Fl nfbs +.Op Fl fc1 | Fl nfc1 +.Op Fl fcb | Fl nfcb +.Ek +.Op Fl i Ns Ar n +.Op Fl \&ip | Fl nip +.Op Fl l Ns Ar n +.Op Fl \&lc Ns Ar n +.Op Fl \&ldi Ns Ar n +.Op Fl \&lp | Fl nlp +.Op Fl \&lpl | Fl nlpl +.Op Fl npro +.Op Fl P Ns Ar file +.Op Fl pcs | Fl npcs +.Op Fl psl | Fl npsl +.Op Fl sac | Fl nsac +.Op Fl \&sc | Fl nsc +.Bk -words +.Op Fl sob | Fl nsob +.Ek +.Op Fl \&st +.Op Fl \&ta +.Op Fl T Ns Ar typename +.Op Fl tpg | Fl ntpg +.Op Fl ts Ns Ar n +.Op Fl U Ns Ar file +.Op Fl ut | Fl nut +.Op Fl v | Fl \&nv +.Op Fl -version +.Sh DESCRIPTION +The +.Nm +utility is a +.Em C +program formatter. +It reformats the +.Em C +program in the +.Ar input-file +according to the switches. +The switches which can be +specified are described below. +They may appear before or after the file +names. +.Pp +.Sy NOTE : +If you only specify an +.Ar input-file , +the formatting is +done `in-place', that is, the formatted file is written back into +.Ar input-file +and a backup copy of +.Ar input-file +is written in the current directory. +If +.Ar input-file +is named +.Sq Pa /blah/blah/file , +the backup file is named +.Sq Pa file.BAK . +.Pp +If +.Ar output-file +is specified, +.Nm +checks to make sure that it is different from +.Ar input-file . +.Pp +The options listed below control the formatting style imposed by +.Nm . +.Bl -tag -width Op +.It Fl bacc , nbacc +If +.Fl bacc +is specified, a blank line is forced around every conditional +compilation block. +For example, in front of every #ifdef and after every #endif. +Other blank lines surrounding such blocks will be swallowed. +Default: +.Fl nbacc . +.It Fl bad , nbad +If +.Fl bad +is specified, a blank line is forced after every block of +declarations. +Default: +.Fl nbad . +.It Fl badp , nbadp +This is vaguely similar to +.Fl bad +except that it only applies to the first set of declarations +in a procedure (just after the first `{') and it causes a blank +line to be generated even if there are no declarations. +The default is +.Fl nbadp. +.It Fl bap , nbap +If +.Fl bap +is specified, a blank line is forced after every procedure body. +Default: +.Fl nbap . +.It Fl bbb , nbbb +If +.Fl bbb +is specified, a blank line is forced before every block comment. +Default: +.Fl nbbb . +.It Fl \&bc , nbc +If +.Fl \&bc +is specified, then a newline is forced after each comma in a declaration. +.Fl nbc +turns off this option. +Default: +.Fl \&nbc . +.It Fl \&bl , \&br +Specifying +.Fl \&bl +lines up compound statements like this: +.Bd -literal -offset indent +if (...) +{ + code +} +.Ed +.Pp +Specifying +.Fl \&br +(the default) makes them look like this: +.Bd -literal -offset indent +if (...) { + code +} +.Ed +.It Fl bs , nbs +Whether a blank should always be inserted after sizeof. +The default is +.Fl nbs. +.It Fl c Ns Ar n +The column in which comments on code start. +The default is 33. +.It Fl cp Ns Ar n +The column in which comments on #else and #endif start. +The default is 0, which effectively separates the directives from comments by +a single space. +.It Fl cd Ns Ar n +The column in which comments on declarations start. +The default +is for these comments to start in the same column as those on code. +.It Fl cdb , ncdb +Enables (disables) the placement of comment delimiters on blank lines. +With +this option enabled, comments look like this: +.Bd -literal -offset indent + /* + * this is a comment + */ +.Ed +.Pp +Rather than like this: +.Bd -literal -offset indent + /* this is a comment */ +.Ed +.Pp +This only affects block comments, not comments to the right of +code. +The default is +.Fl cdb . +.It Fl ce , nce +Enables (disables) forcing of `else's to cuddle up to the immediately preceding +`}'. +The default is +.Fl \&ce . +.It Fl \&ci Ns Ar n +Sets the continuation indent to be +.Ar n . +Continuation +lines will be indented that far from the beginning of the first line of the +statement. +Parenthesized expressions have extra indentation added to +indicate the nesting, unless +.Fl \&lp +is in effect +or the continuation indent is exactly half of the main indent. +.Fl \&ci +defaults to the same value as +.Fl i . +.It Fl cli Ns Ar n +Causes case labels to be indented +.Ar n +tab stops to the right of the containing +.Ic switch +statement. +.Fl cli0.5 +causes case labels to be indented half a tab stop. +The +default is +.Fl cli0 . +.It Fl d Ns Ar n +Controls the placement of comments which are not to the +right of code. +For example, +.Fl \&d\&1 +means that such comments are placed one indentation level to the +left of code. +Specifying the default +.Fl \&d\&0 +lines up these comments with the code. +See the section on comment +indentation below. +.It Fl \&di Ns Ar n +Specifies the indentation, in character positions, +of global variable names and all struct/union member names +relative to the beginning of their type declaration. +The default is +.Fl di16 . +.It Fl dj , ndj +.Fl \&dj +left justifies declarations. +.Fl ndj +indents declarations the same as code. +The default is +.Fl ndj . +.It Fl \&ei , nei +Enables (disables) special +.Ic else-if +processing. +If it is enabled, an +.Ic if +following an +.Ic else +will have the same indentation as the preceding +.Ic \&if +statement. +The default is +.Fl ei . +.It Fl eei , neei +Enables (disables) extra indentation on continuation lines of +the expression part of +.Ic if +and +.Ic while +statements. +These continuation lines will be indented one extra level. +The default is +.Fl neei . +.It Fl fbs , nfbs +Enables (disables) splitting the function declaration and opening brace +across two lines. +The default is +.Fl fbs . +.It Fl fc1 , nfc1 +Enables (disables) the formatting of comments that start in column 1. +Often, comments whose leading `/' is in column 1 have been carefully +hand formatted by the programmer. +In such cases, +.Fl nfc1 +should be +used. +The default is +.Fl fc1 . +.It Fl fcb , nfcb +Enables (disables) the formatting of block comments (ones that begin +with `/*\\n'). +Often, block comments have been not so carefully hand formatted by the +programmer, but reformatting that would just change the line breaks is not +wanted. +In such cases, +.Fl nfcb +should be used. +Block comments are then handled like box comments. +The default is +.Fl fcb . +.It Fl i Ns Ar n +The number of columns for one indentation level. +The default is 8. +.It Fl \&ip , nip +Enables (disables) the indentation of parameter declarations from the left +margin. +The default is +.Fl \&ip . +.It Fl l Ns Ar n +Maximum length of an output line. +The default is 78. +.It Fl lc Ns Ar n +Maximum length of an output line in a block comment. +The default is 0, which means to limit block comment lines in accordance with +.Fl l. +.It Fl \&ldi Ns Ar n +Specifies the indentation, in character positions, +of local variable names +relative to the beginning of their type declaration. +The default is for local variable names to be indented +by the same amount as global ones. +.It Fl \&lp , nlp +Lines up code surrounded by parentheses in continuation lines. +With +.Fl \&lp , +if a line +has a left paren which is not closed on that line, then continuation lines +will be lined up to start at the character position just after the left +paren. +For example, here is how a piece of continued code looks with +.Fl nlp +in effect: +.Bd -literal -offset indent +p1 = first_procedure(second_procedure(p2, p3), +\ \ third_procedure(p4, p5)); +.Ed +.Pp +With +.Fl lp +in effect (the default) the code looks somewhat clearer: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2,\ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4,\ p5)); +.Ed +.Pp +Inserting two more newlines we get: +.Bd -literal -offset indent +p1\ =\ first_procedure(second_procedure(p2, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p3), +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ third_procedure(p4, +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p5)); +.Ed +.It Fl \&lpl , nlpl +With +.Fl \&lpl , +code surrounded by parentheses in continuation lines is lined up even if it +would extend past the right margin. +With +.Fl \&nlpl +(the default), such a line that would extend past the right margin is moved +left to keep it within the margin, if that does not require placing it to +the left of the prevailing indentation level. +These switches have no effect if +.Fl nlp +is selected. +.It Fl npro +Causes the profile files, +.Sq Pa ./.indent.pro +and +.Sq Pa ~/.indent.pro , +to be ignored. +.It Fl P Ns Ar file +Read profile from +.Ar file . +.It Fl pcs , npcs +If true +.Pq Fl pcs +all procedure calls will have a space inserted between +the name and the `('. +The default is +.Fl npcs . +.It Fl psl , npsl +If true +.Pq Fl psl +the names of procedures being defined are placed in +column 1 \- their types, if any, will be left on the previous lines. +The +default is +.Fl psl . +.It Fl sac , nsac +Control whether parenthesized type names in casts are followed by a space or +not. +The default is +.Fl nsac . +.It Fl \&sc , nsc +Enables (disables) the placement of asterisks (`*'s) at the left edge of all +comments. +The default is +.Fl sc . +.It Fl sob , nsob +If +.Fl sob +is specified, indent will swallow optional blank lines. +You can use this to +get rid of blank lines after declarations. +Default: +.Fl nsob . +.It Fl \&st +Causes +.Nm +to take its input from stdin and put its output to stdout. +.It Fl ta +Automatically add all identifiers ending in "_t" to the list +of type keywords. +.It Fl T Ns Ar typename +Adds +.Ar typename +to the list of type keywords. +Names accumulate: +.Fl T +can be specified more than once. +You need to specify all the typenames that +appear in your program that are defined by +.Ic typedef +\- nothing will be +harmed if you miss a few, but the program will not be formatted as nicely as +it should. +This sounds like a painful thing to have to do, but it is really +a symptom of a problem in C: +.Ic typedef +causes a syntactic change in the +language and +.Nm +cannot find all +instances of +.Ic typedef . +.It Fl tpg , ntpg +If +.Fl tpg +is specified, follow Postgres rules about when to use spaces versus +tabs for indentation, that is, use a space instead of a tab if the +tab would move only one column and no tab will follow it. +Default: +.Fl ntpg . +.It Fl ts Ns Ar n +Assumed distance between tab stops. +The default is 8. +.It Fl U Ns Ar file +Adds type names from +.Ar file +to the list of type keywords. +.It Fl ut , nut +Enables (disables) the use of tab characters in the output. +The default is +.Fl ut . +.It Fl v , \&nv +.Fl v +turns on `verbose' mode; +.Fl \&nv +turns it off. +When in verbose mode, +.Nm +reports when it splits one line of input into two or more lines of output, +and gives some size statistics at completion. +The default is +.Fl \&nv . +.It Fl -version +Causes +.Nm +to print its version number and exit. +.El +.Pp +You may set up your own `profile' of defaults to +.Nm +by creating a file called +.Pa .indent.pro +in your login directory and/or the current directory and including +whatever switches you like. +A `.indent.pro' in the current directory takes +precedence over the one in your login directory. +If +.Nm +is run and a profile file exists, then it is read to set up the program's +defaults. +Switches on the command line, though, always override profile +switches. +The switches should be separated by spaces, tabs or newlines. +.Pp +.Ss Comments +.Sq Em Box +.Em comments . +The +.Nm +utility +assumes that any comment with a dash or star immediately after the start of +comment (that is, `/*\-' or `/**') is a comment surrounded by a box of stars. +Each line of such a comment is left unchanged, except that its indentation +may be adjusted to account for the change in indentation of the first line +of the comment. +.Pp +.Em Straight text . +All other comments are treated as straight text. +The +.Nm +utility fits as many words (separated by blanks, tabs, or newlines) on a +line as possible. +Blank lines break paragraphs. +.Ss Comment indentation +If a comment is on a line with code it is started in the `comment column', +which is set by the +.Fl c Ns Ns Ar n +command line parameter. +Otherwise, the comment is started at +.Ar n +indentation levels less than where code is currently being placed, where +.Ar n +is specified by the +.Fl d Ns Ns Ar n +command line parameter. +If the code on a line extends past the comment +column, the comment starts further to the right, and the right margin may be +automatically extended in extreme cases. +.Ss Preprocessor lines +In general, +.Nm +leaves preprocessor lines alone. +The only +reformatting that it will do is to straighten up trailing comments. +It +leaves embedded comments alone. +Conditional compilation +.Pq Ic #ifdef...#endif +is recognized and +.Nm +attempts to correctly +compensate for the syntactic peculiarities introduced. +.Ss C syntax +The +.Nm +utility understands a substantial amount about the syntax of C, but it +has a `forgiving' parser. +It attempts to cope with the usual sorts of +incomplete and malformed syntax. +In particular, the use of macros like: +.Pp +.Dl #define forever for(;;) +.Pp +is handled properly. +.Sh ENVIRONMENT +The +.Nm +utility uses the +.Ev HOME +environment variable. +.Sh FILES +.Bl -tag -width "./.indent.pro" -compact +.It Pa ./.indent.pro +profile file +.It Pa ~/.indent.pro +profile file +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +The +.Nm +utility has even more switches than +.Xr ls 1 . +.Pp +A common mistake is to try to indent all the +.Em C +programs in a directory by typing: +.Pp +.Dl indent *.c +.Pp +This is probably a bug, not a feature. diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c new file mode 100644 index 0000000000..d3a0ecefe9 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.c @@ -0,0 +1,1279 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1976 Board of Trustees of the University of Illinois. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <sys/param.h> +#include <err.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +/* Tell indent_globs.h to define our global variables here */ +#define DECLARE_INDENT_GLOBALS 1 + +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void bakcopy(void); +static void indent_declaration(int, int); + +const char *in_name = "Standard Input"; /* will always point to name of input + * file */ +const char *out_name = "Standard Output"; /* will always point to name + * of output file */ +char bakfile[MAXPATHLEN] = ""; + +int +main(int argc, char **argv) +{ + int dec_ind; /* current indentation for declarations */ + int di_stack[20]; /* a stack of structure indentation levels */ + int force_nl; /* when true, code must be broken */ + int hd_type = 0; /* used to store type of stmt for if (...), + * for (...), etc */ + int i; /* local loop counter */ + int scase; /* set to true when we see a case, so we will + * know what to do with the following colon */ + int sp_sw; /* when true, we are in the expression of + * if(...), while(...), etc. */ + int squest; /* when this is positive, we have seen a ? + * without the matching : in a <c>?<s>:<s> + * construct */ + const char *t_ptr; /* used for copying tokens */ + int tabs_to_var; /* true if using tabs to indent to var name */ + int type_code; /* the type of token, returned by lexi */ + + int last_else = 0; /* true iff last keyword was an else */ + const char *profile_name = NULL; + struct parser_state transient_state; /* a copy for lookup */ + + + /*-----------------------------------------------*\ + | INITIALIZATION | + \*-----------------------------------------------*/ + + found_err = 0; + + ps.p_stack[0] = stmt; /* this is the parser's stack */ + ps.last_nl = true; /* this is true if the last thing scanned was + * a newline */ + ps.last_token = semicolon; + combuf = (char *) malloc(bufsize); + if (combuf == NULL) + err(1, NULL); + labbuf = (char *) malloc(bufsize); + if (labbuf == NULL) + err(1, NULL); + codebuf = (char *) malloc(bufsize); + if (codebuf == NULL) + err(1, NULL); + tokenbuf = (char *) malloc(bufsize); + if (tokenbuf == NULL) + err(1, NULL); + alloc_typenames(); + l_com = combuf + bufsize - 5; + l_lab = labbuf + bufsize - 5; + l_code = codebuf + bufsize - 5; + l_token = tokenbuf + bufsize - 5; + combuf[0] = codebuf[0] = labbuf[0] = ' '; /* set up code, label, and + * comment buffers */ + combuf[1] = codebuf[1] = labbuf[1] = '\0'; + ps.else_if = 1; /* Default else-if special processing to on */ + s_lab = e_lab = labbuf + 1; + s_code = e_code = codebuf + 1; + s_com = e_com = combuf + 1; + s_token = e_token = tokenbuf + 1; + + in_buffer = (char *) malloc(10); + if (in_buffer == NULL) + err(1, NULL); + in_buffer_limit = in_buffer + 8; + buf_ptr = buf_end = in_buffer; + line_no = 1; + had_eof = ps.in_decl = ps.decl_on_line = break_comma = false; + sp_sw = force_nl = false; + ps.in_or_st = false; + ps.bl_line = true; + dec_ind = 0; + di_stack[ps.dec_nest = 0] = 0; + ps.want_blank = ps.in_stmt = ps.ind_stmt = false; + + scase = ps.pcase = false; + squest = 0; + sc_end = NULL; + bp_save = NULL; + be_save = NULL; + + output = NULL; + tabs_to_var = 0; + + /*--------------------------------------------------*\ + | COMMAND LINE SCAN | + \*--------------------------------------------------*/ + +#ifdef undef + max_col = 78; /* -l78 */ + lineup_to_parens = 1; /* -lp */ + lineup_to_parens_always = 0; /* -nlpl */ + ps.ljust_decl = 0; /* -ndj */ + ps.com_ind = 33; /* -c33 */ + star_comment_cont = 1; /* -sc */ + ps.ind_size = 8; /* -i8 */ + verbose = 0; + ps.decl_indent = 16; /* -di16 */ + ps.local_decl_indent = -1; /* if this is not set to some nonnegative value + * by an arg, we will set this equal to + * ps.decl_ind */ + ps.indent_parameters = 1; /* -ip */ + ps.decl_com_ind = 0; /* if this is not set to some positive value + * by an arg, we will set this equal to + * ps.com_ind */ + btype_2 = 1; /* -br */ + cuddle_else = 1; /* -ce */ + ps.unindent_displace = 0; /* -d0 */ + ps.case_indent = 0; /* -cli0 */ + format_block_comments = 1; /* -fcb */ + format_col1_comments = 1; /* -fc1 */ + procnames_start_line = 1; /* -psl */ + proc_calls_space = 0; /* -npcs */ + comment_delimiter_on_blankline = 1; /* -cdb */ + ps.leave_comma = 1; /* -nbc */ +#endif + + for (i = 1; i < argc; ++i) + if (strcmp(argv[i], "-npro") == 0) + break; + else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0') + profile_name = argv[i]; /* non-empty -P (set profile) */ + set_defaults(); + if (i >= argc) + set_profile(profile_name); + + for (i = 1; i < argc; ++i) { + + /* + * look thru args (if any) for changes to defaults + */ + if (argv[i][0] != '-') {/* no flag on parameter */ + if (input == NULL) { /* we must have the input file */ + in_name = argv[i]; /* remember name of input file */ + input = fopen(in_name, "r"); + if (input == NULL) /* check for open error */ + err(1, "%s", in_name); + continue; + } + else if (output == NULL) { /* we have the output file */ + out_name = argv[i]; /* remember name of output file */ + if (strcmp(in_name, out_name) == 0) { /* attempt to overwrite + * the file */ + errx(1, "input and output files must be different"); + } + output = fopen(out_name, "w"); + if (output == NULL) /* check for create error */ + err(1, "%s", out_name); + continue; + } + errx(1, "unknown parameter: %s", argv[i]); + } + else + set_option(argv[i]); + } /* end of for */ + if (input == NULL) + input = stdin; + if (output == NULL) { + if (input == stdin) + output = stdout; + else { + out_name = in_name; + bakcopy(); + } + } + + if (ps.com_ind <= 1) + ps.com_ind = 2; /* dont put normal comments before column 2 */ + if (block_comment_max_col <= 0) + block_comment_max_col = max_col; + if (ps.local_decl_indent < 0) /* if not specified by user, set this */ + ps.local_decl_indent = ps.decl_indent; + if (ps.decl_com_ind <= 0) /* if not specified by user, set this */ + ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind; + if (continuation_indent == 0) + continuation_indent = ps.ind_size; + fill_buffer(); /* get first batch of stuff into input buffer */ + + parse(semicolon); + { + char *p = buf_ptr; + int col = 1; + + while (1) { + if (*p == ' ') + col++; + else if (*p == '\t') + col = tabsize * (1 + (col - 1) / tabsize) + 1; + else + break; + p++; + } + if (col > ps.ind_size) + ps.ind_level = ps.i_l_follow = col / ps.ind_size; + } + + /* + * START OF MAIN LOOP + */ + + while (1) { /* this is the main loop. it will go until we + * reach eof */ + int comment_buffered = false; + + type_code = lexi(&ps); /* lexi reads one token. The actual + * characters read are stored in "token". lexi + * returns a code indicating the type of token */ + + /* + * The following code moves newlines and comments following an if (), + * while (), else, etc. up to the start of the following stmt to + * a buffer. This allows proper handling of both kinds of brace + * placement (-br, -bl) and cuddling "else" (-ce). + */ + + while (ps.search_brace) { + switch (type_code) { + case newline: + if (sc_end == NULL) { + save_com = sc_buf; + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + *sc_end++ = '\n'; + /* + * We may have inherited a force_nl == true from the previous + * token (like a semicolon). But once we know that a newline + * has been scanned in this loop, force_nl should be false. + * + * However, the force_nl == true must be preserved if newline + * is never scanned in this loop, so this assignment cannot be + * done earlier. + */ + force_nl = false; + case form_feed: + break; + case comment: + if (sc_end == NULL) { + /* + * Copy everything from the start of the line, because + * pr_comment() will use that to calculate original + * indentation of a boxed comment. + */ + memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4); + save_com = sc_buf + (buf_ptr - in_buffer - 4); + save_com[0] = save_com[1] = ' '; + sc_end = &save_com[2]; + } + comment_buffered = true; + *sc_end++ = '/'; /* copy in start of comment */ + *sc_end++ = '*'; + for (;;) { /* loop until we get to the end of the comment */ + *sc_end = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*sc_end++ == '*' && *buf_ptr == '/') + break; /* we are at end of comment */ + if (sc_end >= &save_com[sc_size]) { /* check for temp buffer + * overflow */ + diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever"); + fflush(output); + exit(1); + } + } + *sc_end++ = '/'; /* add ending slash */ + if (++buf_ptr >= buf_end) /* get past / in buffer */ + fill_buffer(); + break; + case lbrace: + /* + * Put KNF-style lbraces before the buffered up tokens and + * jump out of this loop in order to avoid copying the token + * again under the default case of the switch below. + */ + if (sc_end != NULL && btype_2) { + save_com[0] = '{'; + /* + * Originally the lbrace may have been alone on its own + * line, but it will be moved into "the else's line", so + * if there was a newline resulting from the "{" before, + * it must be scanned now and ignored. + */ + while (isspace((unsigned char)*buf_ptr)) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '\n') + break; + } + goto sw_buffer; + } + /* FALLTHROUGH */ + default: /* it is the start of a normal statement */ + { + int remove_newlines; + + remove_newlines = + /* "} else" */ + (type_code == sp_nparen && *token == 'e' && + e_code != s_code && e_code[-1] == '}') + /* "else if" */ + || (type_code == sp_paren && *token == 'i' && + last_else && ps.else_if); + if (remove_newlines) + force_nl = false; + if (sc_end == NULL) { /* ignore buffering if + * comment wasn't saved up */ + ps.search_brace = false; + goto check_type; + } + while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) { + sc_end--; + } + if (swallow_optional_blanklines || + (!comment_buffered && remove_newlines)) { + force_nl = !remove_newlines; + while (sc_end > save_com && sc_end[-1] == '\n') { + sc_end--; + } + } + if (force_nl) { /* if we should insert a nl here, put + * it into the buffer */ + force_nl = false; + --line_no; /* this will be re-increased when the + * newline is read from the buffer */ + *sc_end++ = '\n'; + *sc_end++ = ' '; + if (verbose) /* print error msg if the line was + * not already broken */ + diag2(0, "Line broken"); + } + for (t_ptr = token; *t_ptr; ++t_ptr) + *sc_end++ = *t_ptr; + + sw_buffer: + ps.search_brace = false; /* stop looking for start of + * stmt */ + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' ';/* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + break; + } + } /* end of switch */ + /* + * We must make this check, just in case there was an unexpected + * EOF. + */ + if (type_code != 0) { + /* + * The only intended purpose of calling lexi() below is to + * categorize the next token in order to decide whether to + * continue buffering forthcoming tokens. Once the buffering + * is over, lexi() will be called again elsewhere on all of + * the tokens - this time for normal processing. + * + * Calling it for this purpose is a bug, because lexi() also + * changes the parser state and discards leading whitespace, + * which is needed mostly for comment-related considerations. + * + * Work around the former problem by giving lexi() a copy of + * the current parser state and discard it if the call turned + * out to be just a look ahead. + * + * Work around the latter problem by copying all whitespace + * characters into the buffer so that the later lexi() call + * will read them. + */ + if (sc_end != NULL) { + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + *sc_end++ = *buf_ptr++; + if (sc_end >= &save_com[sc_size]) { + errx(1, "input too long"); + } + } + if (buf_ptr >= buf_end) { + fill_buffer(); + } + } + transient_state = ps; + type_code = lexi(&transient_state); /* read another token */ + if (type_code != newline && type_code != form_feed && + type_code != comment && !transient_state.search_brace) { + ps = transient_state; + } + } + } /* end of while (search_brace) */ + last_else = 0; +check_type: + if (type_code == 0) { /* we got eof */ + if (s_lab != e_lab || s_code != e_code + || s_com != e_com) /* must dump end of line */ + dump_line(); + if (ps.tos > 1) /* check for balanced braces */ + diag2(1, "Stuff missing from end of file"); + + if (verbose) { + printf("There were %d output lines and %d comments\n", + ps.out_lines, ps.out_coms); + printf("(Lines with comments)/(Lines with code): %6.3f\n", + (1.0 * ps.com_lines) / code_lines); + } + fflush(output); + exit(found_err); + } + if ( + (type_code != comment) && + (type_code != newline) && + (type_code != preesc) && + (type_code != form_feed)) { + if (force_nl && + (type_code != semicolon) && + (type_code != lbrace || !btype_2)) { + /* we should force a broken line here */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; /* dont insert blank at line start */ + force_nl = false; + } + ps.in_stmt = true; /* turn on flag which causes an extra level of + * indentation. this is turned off by a ; or + * '}' */ + if (s_com != e_com) { /* the turkey has embedded a comment + * in a line. fix it */ + int len = e_com - s_com; + + CHECK_SIZE_CODE(len + 3); + *e_code++ = ' '; + memcpy(e_code, s_com, len); + e_code += len; + *e_code++ = ' '; + *e_code = '\0'; /* null terminate code sect */ + ps.want_blank = false; + e_com = s_com; + } + } + else if (type_code != comment) /* preserve force_nl thru a comment */ + force_nl = false; /* cancel forced newline after newline, form + * feed, etc */ + + + + /*-----------------------------------------------------*\ + | do switch on type of token scanned | + \*-----------------------------------------------------*/ + CHECK_SIZE_CODE(3); /* maximum number of increments of e_code + * before the next CHECK_SIZE_CODE or + * dump_line() is 2. After that there's the + * final increment for the null character. */ + switch (type_code) { /* now, decide what to do with the token */ + + case form_feed: /* found a form feed in line */ + ps.use_ff = true; /* a form feed is treated much like a newline */ + dump_line(); + ps.want_blank = false; + break; + + case newline: + if (ps.last_token != comma || ps.p_l_follow > 0 + || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) { + dump_line(); + ps.want_blank = false; + } + ++line_no; /* keep track of input line number */ + break; + + case lparen: /* got a '(' or '[' */ + /* count parens to make Healy happy */ + if (++ps.p_l_follow == nitems(ps.paren_indents)) { + diag3(0, "Reached internal limit of %d unclosed parens", + nitems(ps.paren_indents)); + ps.p_l_follow--; + } + if (*token == '[') + /* not a function pointer declaration or a function call */; + else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* function pointer declarations */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank && + ((ps.last_token != ident && ps.last_token != funcname) || + /* offsetof (1) is never allowed a space; sizeof (2) gets + * one iff -bs; all other keywords (>2) always get a space + * before lparen */ + ps.keyword + Bill_Shannon > 2)) + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = token[0]; + ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1; + if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent + && ps.paren_indents[0] < 2 * ps.ind_size) + ps.paren_indents[0] = 2 * ps.ind_size; + if (ps.in_or_st && *token == '(' && ps.tos <= 2) { + /* + * this is a kluge to make sure that declarations will be + * aligned right if proc decl has an explicit type on it, i.e. + * "int a(x) {..." + */ + parse(semicolon); /* I said this was a kluge... */ + ps.in_or_st = false; /* turn off flag for structure decl or + * initialization */ + } + /* + * parenthesized type following sizeof or offsetof is not a cast, + * and we assume the same for any other non-keyword identifier, + * to support macros that take types + */ + if (ps.last_token == ident && + (ps.keyword == 0 || ps.keyword == 1 || ps.keyword == 2)) + ps.not_cast_mask |= 1 << ps.p_l_follow; + break; + + case rparen: /* got a ')' or ']' */ + if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) { + ps.last_u_d = true; + ps.cast_mask &= (1 << ps.p_l_follow) - 1; + ps.want_blank = space_after_cast; + } else + ps.want_blank = true; + ps.not_cast_mask &= (1 << ps.p_l_follow) - 1; + if (--ps.p_l_follow < 0) { + ps.p_l_follow = 0; + diag3(0, "Extra %c", *token); + } + if (e_code == s_code) /* if the paren starts the line */ + ps.paren_level = ps.p_l_follow; /* then indent it */ + + *e_code++ = token[0]; + + if (sp_sw && (ps.p_l_follow == 0)) { /* check for end of if + * (...), or some such */ + sp_sw = false; + force_nl = true;/* must force newline after if */ + ps.last_u_d = true; /* inform lexi that a following + * operator is unary */ + ps.in_stmt = false; /* dont use stmt continuation + * indentation */ + + parse(hd_type); /* let parser worry about if, or whatever */ + } + ps.search_brace = btype_2; /* this should insure that constructs + * such as main(){...} and int[]{...} + * have their braces put in the right + * place */ + break; + + case unary_op: /* this could be any unary operation */ + if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init && + ps.procname[0] == '\0' && ps.paren_level == 0) { + /* pointer declarations */ + + /* + * if this is a unary op in a declaration, we should indent + * this token + */ + for (i = 0; token[i]; ++i) + /* find length of token */; + indent_declaration(dec_ind - i, tabs_to_var); + ps.dumped_decl_indent = true; + } + else if (ps.want_blank) + *e_code++ = ' '; + + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len); + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case binary_op: /* any binary operation */ + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = true; + break; + + case postop: /* got a trailing ++ or -- */ + *e_code++ = token[0]; + *e_code++ = token[1]; + ps.want_blank = true; + break; + + case question: /* got a ? */ + squest++; /* this will be used when a later colon + * appears so we can distinguish the + * <c>?<n>:<n> construct */ + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = '?'; + ps.want_blank = true; + break; + + case casestmt: /* got word 'case' or 'default' */ + scase = true; /* so we can process the later colon properly */ + goto copy_id; + + case colon: /* got a ':' */ + if (squest > 0) { /* it is part of the <c>?<n>: <n> construct */ + --squest; + if (ps.want_blank) + *e_code++ = ' '; + *e_code++ = ':'; + ps.want_blank = true; + break; + } + if (ps.in_or_st) { + *e_code++ = ':'; + ps.want_blank = false; + break; + } + ps.in_stmt = false; /* seeing a label does not imply we are in a + * stmt */ + /* + * turn everything so far into a label + */ + { + int len = e_code - s_code; + + CHECK_SIZE_LAB(len + 3); + memcpy(e_lab, s_code, len); + e_lab += len; + *e_lab++ = ':'; + *e_lab = '\0'; + e_code = s_code; + } + force_nl = ps.pcase = scase; /* ps.pcase will be used by + * dump_line to decide how to + * indent the label. force_nl + * will force a case n: to be + * on a line by itself */ + scase = false; + ps.want_blank = false; + break; + + case semicolon: /* got a ';' */ + if (ps.dec_nest == 0) + ps.in_or_st = false;/* we are not in an initialization or + * structure declaration */ + scase = false; /* these will only need resetting in an error */ + squest = 0; + if (ps.last_token == rparen) + ps.in_parameter_declaration = 0; + ps.cast_mask = 0; + ps.not_cast_mask = 0; + ps.block_init = 0; + ps.block_init_level = 0; + ps.just_saw_decl--; + + if (ps.in_decl && s_code == e_code && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent stray semicolons in declarations */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + + ps.in_decl = (ps.dec_nest > 0); /* if we were in a first level + * structure declaration, we + * arent any more */ + + if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) { + + /* + * This should be true iff there were unbalanced parens in the + * stmt. It is a bit complicated, because the semicolon might + * be in a for stmt + */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* this is a check for an if, while, etc. with + * unbalanced parens */ + sp_sw = false; + parse(hd_type); /* dont lose the if, or whatever */ + } + } + *e_code++ = ';'; + ps.want_blank = true; + ps.in_stmt = (ps.p_l_follow > 0); /* we are no longer in the + * middle of a stmt */ + + if (!sp_sw) { /* if not if for (;;) */ + parse(semicolon); /* let parser know about end of stmt */ + force_nl = true;/* force newline after an end of stmt */ + } + break; + + case lbrace: /* got a '{' */ + ps.in_stmt = false; /* dont indent the {} */ + if (!ps.block_init) + force_nl = true;/* force other stuff on same line as '{' onto + * new line */ + else if (ps.block_init_level <= 0) + ps.block_init_level = 1; + else + ps.block_init_level++; + + if (s_code != e_code && !ps.block_init) { + if (!btype_2) { + dump_line(); + ps.want_blank = false; + } + else if (ps.in_parameter_declaration && !ps.in_or_st) { + ps.i_l_follow = 0; + if (function_brace_split) { /* dump the line prior to the + * brace ... */ + dump_line(); + ps.want_blank = false; + } else /* add a space between the decl and brace */ + ps.want_blank = true; + } + } + if (ps.in_parameter_declaration) + prefix_blankline_requested = 0; + + if (ps.p_l_follow > 0) { /* check for preceding unbalanced + * parens */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + if (sp_sw) { /* check for unclosed if, for, etc. */ + sp_sw = false; + parse(hd_type); + ps.ind_level = ps.i_l_follow; + } + } + if (s_code == e_code) + ps.ind_stmt = false; /* dont put extra indentation on line + * with '{' */ + if (ps.in_decl && ps.in_or_st) { /* this is either a structure + * declaration or an init */ + di_stack[ps.dec_nest] = dec_ind; + if (++ps.dec_nest == nitems(di_stack)) { + diag3(0, "Reached internal limit of %d struct levels", + nitems(di_stack)); + ps.dec_nest--; + } + /* ? dec_ind = 0; */ + } + else { + ps.decl_on_line = false; /* we can't be in the middle of + * a declaration, so don't do + * special indentation of + * comments */ + if (blanklines_after_declarations_at_proctop + && ps.in_parameter_declaration) + postfix_blankline_requested = 1; + ps.in_parameter_declaration = 0; + ps.in_decl = false; + } + dec_ind = 0; + parse(lbrace); /* let parser know about this */ + if (ps.want_blank) /* put a blank before '{' if '{' is not at + * start of line */ + *e_code++ = ' '; + ps.want_blank = false; + *e_code++ = '{'; + ps.just_saw_decl = 0; + break; + + case rbrace: /* got a '}' */ + if (ps.p_stack[ps.tos] == decl && !ps.block_init) /* semicolons can be + * omitted in + * declarations */ + parse(semicolon); + if (ps.p_l_follow) {/* check for unclosed if, for, else. */ + diag2(1, "Unbalanced parens"); + ps.p_l_follow = 0; + sp_sw = false; + } + ps.just_saw_decl = 0; + ps.block_init_level--; + if (s_code != e_code && !ps.block_init) { /* '}' must be first on + * line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + } + *e_code++ = '}'; + ps.want_blank = true; + ps.in_stmt = ps.ind_stmt = false; + if (ps.dec_nest > 0) { /* we are in multi-level structure + * declaration */ + dec_ind = di_stack[--ps.dec_nest]; + if (ps.dec_nest == 0 && !ps.in_parameter_declaration) + ps.just_saw_decl = 2; + ps.in_decl = true; + } + prefix_blankline_requested = 0; + parse(rbrace); /* let parser know about this */ + ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead + && ps.il[ps.tos] >= ps.ind_level; + if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0) + postfix_blankline_requested = 1; + break; + + case swstmt: /* got keyword "switch" */ + sp_sw = true; + hd_type = swstmt; /* keep this for when we have seen the + * expression */ + goto copy_id; /* go move the token into buffer */ + + case sp_paren: /* token is if, while, for */ + sp_sw = true; /* the interesting stuff is done after the + * expression is scanned */ + hd_type = (*token == 'i' ? ifstmt : + (*token == 'w' ? whilestmt : forstmt)); + + /* + * remember the type of header for later use by parser + */ + goto copy_id; /* copy the token into line */ + + case sp_nparen: /* got else, do */ + ps.in_stmt = false; + if (*token == 'e') { + if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) { + if (verbose) + diag2(0, "Line broken"); + dump_line();/* make sure this starts a line */ + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 1; + parse(elselit); + } + else { + if (e_code != s_code) { /* make sure this starts a line */ + if (verbose) + diag2(0, "Line broken"); + dump_line(); + ps.want_blank = false; + } + force_nl = true;/* also, following stuff must go onto new line */ + last_else = 0; + parse(dolit); + } + goto copy_id; /* move the token into line */ + + case type_def: + case storage: + prefix_blankline_requested = 0; + goto copy_id; + + case structure: + if (ps.p_l_follow > 0) + goto copy_id; + /* FALLTHROUGH */ + case decl: /* we have a declaration type (int, etc.) */ + parse(decl); /* let parser worry about indentation */ + if (ps.last_token == rparen && ps.tos <= 1) { + if (s_code != e_code) { + dump_line(); + ps.want_blank = 0; + } + } + if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) { + ps.ind_level = ps.i_l_follow = 1; + ps.ind_stmt = 0; + } + ps.in_or_st = true; /* this might be a structure or initialization + * declaration */ + ps.in_decl = ps.decl_on_line = true; + if ( /* !ps.in_or_st && */ ps.dec_nest <= 0) + ps.just_saw_decl = 2; + prefix_blankline_requested = 0; + for (i = 0; token[i++];); /* get length of token */ + + if (ps.ind_level == 0 || ps.dec_nest > 0) { + /* global variable or struct member in local variable */ + dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i; + tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0); + } else { + /* local variable */ + dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i; + tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0); + } + goto copy_id; + + case funcname: + case ident: /* got an identifier or constant */ + if (ps.in_decl) { + if (type_code == funcname) { + ps.in_decl = false; + if (procnames_start_line && s_code != e_code) { + *e_code = '\0'; + dump_line(); + } + else if (ps.want_blank) { + *e_code++ = ' '; + } + ps.want_blank = false; + } + else if (!ps.block_init && !ps.dumped_decl_indent && + ps.paren_level == 0) { /* if we are in a declaration, we + * must indent identifier */ + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + ps.want_blank = false; + } + } + else if (sp_sw && ps.p_l_follow == 0) { + sp_sw = false; + force_nl = true; + ps.last_u_d = true; + ps.in_stmt = false; + parse(hd_type); + } + copy_id: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, s_token, len); + e_code += len; + } + if (type_code != funcname) + ps.want_blank = true; + break; + + case strpfx: + { + int len = e_token - s_token; + + CHECK_SIZE_CODE(len + 1); + if (ps.want_blank) + *e_code++ = ' '; + memcpy(e_code, token, len); + e_code += len; + } + ps.want_blank = false; + break; + + case period: /* treat a period kind of like a binary + * operation */ + *e_code++ = '.'; /* move the period into line */ + ps.want_blank = false; /* dont put a blank after a period */ + break; + + case comma: + ps.want_blank = (s_code != e_code); /* only put blank after comma + * if comma does not start the + * line */ + if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init && + !ps.dumped_decl_indent && ps.paren_level == 0) { + /* indent leading commas and not the actual identifiers */ + indent_declaration(dec_ind - 1, tabs_to_var); + ps.dumped_decl_indent = true; + } + *e_code++ = ','; + if (ps.p_l_follow == 0) { + if (ps.block_init_level <= 0) + ps.block_init = 0; + if (break_comma && (!ps.leave_comma || + count_spaces_until(compute_code_target(), s_code, e_code) > + max_col - tabsize)) + force_nl = true; + } + break; + + case preesc: /* got the character '#' */ + if ((s_com != e_com) || + (s_lab != e_lab) || + (s_code != e_code)) + dump_line(); + CHECK_SIZE_LAB(1); + *e_lab++ = '#'; /* move whole line to 'label' buffer */ + { + int in_comment = 0; + int com_start = 0; + char quote = 0; + int com_end = 0; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { + buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + while (*buf_ptr != '\n' || (in_comment && !had_eof)) { + CHECK_SIZE_LAB(2); + *e_lab = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + switch (*e_lab++) { + case BACKSLASH: + if (!in_comment) { + *e_lab++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + break; + case '/': + if (*buf_ptr == '*' && !in_comment && !quote) { + in_comment = 1; + *e_lab++ = *buf_ptr++; + com_start = e_lab - s_lab - 2; + } + break; + case '"': + if (quote == '"') + quote = 0; + break; + case '\'': + if (quote == '\'') + quote = 0; + break; + case '*': + if (*buf_ptr == '/' && in_comment) { + in_comment = 0; + *e_lab++ = *buf_ptr++; + com_end = e_lab - s_lab; + } + break; + } + } + + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + if (e_lab - s_lab == com_end && bp_save == NULL) { + /* comment on preprocessor line */ + if (sc_end == NULL) { /* if this is the first comment, + * we must set up the buffer */ + save_com = sc_buf; + sc_end = &save_com[0]; + } + else { + *sc_end++ = '\n'; /* add newline between + * comments */ + *sc_end++ = ' '; + --line_no; + } + if (sc_end - save_com + com_end - com_start > sc_size) + errx(1, "input too long"); + memmove(sc_end, s_lab + com_start, com_end - com_start); + sc_end += com_end - com_start; + e_lab = s_lab + com_start; + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + bp_save = buf_ptr; /* save current input buffer */ + be_save = buf_end; + buf_ptr = save_com; /* fix so that subsequent calls to + * lexi will take tokens out of + * save_com */ + *sc_end++ = ' '; /* add trailing blank, just in case */ + buf_end = sc_end; + sc_end = NULL; + } + CHECK_SIZE_LAB(1); + *e_lab = '\0'; /* null terminate line */ + ps.pcase = false; + } + + if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */ + if ((size_t)ifdef_level < nitems(state_stack)) { + match_state[ifdef_level].tos = -1; + state_stack[ifdef_level++] = ps; + } + else + diag2(1, "#if stack overflow"); + } + else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */ + if (ifdef_level <= 0) + diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else"); + else { + match_state[ifdef_level - 1] = ps; + ps = state_stack[ifdef_level - 1]; + } + } + else if (strncmp(s_lab, "#endif", 6) == 0) { + if (ifdef_level <= 0) + diag2(1, "Unmatched #endif"); + else + ifdef_level--; + } else { + struct directives { + int size; + const char *string; + } + recognized[] = { + {7, "include"}, + {6, "define"}, + {5, "undef"}, + {4, "line"}, + {5, "error"}, + {6, "pragma"} + }; + int d = nitems(recognized); + while (--d >= 0) + if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0) + break; + if (d < 0) { + diag2(1, "Unrecognized cpp directive"); + break; + } + } + if (blanklines_around_conditional_compilation) { + postfix_blankline_requested++; + n_real_blanklines = 0; + } + else { + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + } + break; /* subsequent processing of the newline + * character will cause the line to be printed */ + + case comment: /* we have gotten a / followed by * this is a biggie */ + pr_comment(); + break; + } /* end of big switch stmt */ + + *e_code = '\0'; /* make sure code section is null terminated */ + if (type_code != comment && type_code != newline && type_code != preesc) + ps.last_token = type_code; + } /* end of main while (1) loop */ +} + +/* + * copy input file to backup file if in_name is /blah/blah/blah/file, then + * backup file will be ".Bfile" then make the backup file the input and + * original input file the output + */ +static void +bakcopy(void) +{ + int n, + bakchn; + char buff[8 * 1024]; + const char *p; + + /* construct file name .Bfile */ + for (p = in_name; *p; p++); /* skip to end of string */ + while (p > in_name && *p != '/') /* find last '/' */ + p--; + if (*p == '/') + p++; + sprintf(bakfile, "%s.BAK", p); + + /* copy in_name to backup file */ + bakchn = creat(bakfile, 0600); + if (bakchn < 0) + err(1, "%s", bakfile); + while ((n = read(fileno(input), buff, sizeof(buff))) > 0) + if (write(bakchn, buff, n) != n) + err(1, "%s", bakfile); + if (n < 0) + err(1, "%s", in_name); + close(bakchn); + fclose(input); + + /* re-open backup file as the input file */ + input = fopen(bakfile, "r"); + if (input == NULL) + err(1, "%s", bakfile); + /* now the original input file will be the output */ + output = fopen(in_name, "w"); + if (output == NULL) { + unlink(bakfile); + err(1, "%s", in_name); + } +} + +static void +indent_declaration(int cur_dec_ind, int tabs_to_var) +{ + int pos = e_code - s_code; + char *startpos = e_code; + + /* + * get the tab math right for indentations that are not multiples of tabsize + */ + if ((ps.ind_level * ps.ind_size) % tabsize != 0) { + pos += (ps.ind_level * ps.ind_size) % tabsize; + cur_dec_ind += (ps.ind_level * ps.ind_size) % tabsize; + } + if (tabs_to_var) { + int tpos; + + CHECK_SIZE_CODE(cur_dec_ind / tabsize); + while ((tpos = tabsize * (1 + pos / tabsize)) <= cur_dec_ind) { + *e_code++ = (!postgres_tab_rules || + tpos != pos + 1 || + cur_dec_ind >= tpos + tabsize) ? '\t' : ' '; + pos = tpos; + } + } + CHECK_SIZE_CODE(cur_dec_ind - pos + 1); + while (pos < cur_dec_ind) { + *e_code++ = ' '; + pos++; + } + if (e_code == startpos && ps.want_blank) { + *e_code++ = ' '; + ps.want_blank = false; + } +} diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h new file mode 100644 index 0000000000..1708dbc19f --- /dev/null +++ b/src/tools/pg_bsd_indent/indent.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2001 Jens Schweikhardt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); +#endif + +#define nitems(array) (sizeof (array) / sizeof (array[0])) + +void add_typename(const char *); +void alloc_typenames(void); +int compute_code_target(void); +int compute_label_target(void); +int count_spaces(int, char *); +int count_spaces_until(int, char *, char *); +int lexi(struct parser_state *); +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); +void set_defaults(void); +void set_option(char *); +void set_profile(const char *); diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h new file mode 100644 index 0000000000..24c43fa420 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_codes.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_codes.h 309380 2016-12-02 01:25:51Z pfg $ + */ + +#define newline 1 +#define lparen 2 +#define rparen 3 +#define unary_op 4 +#define binary_op 5 +#define postop 6 +#define question 7 +#define casestmt 8 +#define colon 9 +#define semicolon 10 +#define lbrace 11 +#define rbrace 12 +#define ident 13 +#define comma 14 +#define comment 15 +#define swstmt 16 +#define preesc 17 +#define form_feed 18 +#define decl 19 +#define sp_paren 20 +#define sp_nparen 21 +#define ifstmt 22 +#define whilestmt 23 +#define forstmt 24 +#define stmt 25 +#define stmtl 26 +#define elselit 27 +#define dolit 28 +#define dohead 29 +#define ifhead 30 +#define elsehead 31 +#define period 32 +#define strpfx 33 +#define storage 34 +#define funcname 35 +#define type_def 36 +#define structure 37 diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h new file mode 100644 index 0000000000..398784b3f4 --- /dev/null +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -0,0 +1,343 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)indent_globs.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: head/usr.bin/indent/indent_globs.h 303735 2016-08-03 22:08:07Z pfg $ + */ + +#define BACKSLASH '\\' +#define bufsize 200 /* size of internal buffers */ +#define sc_size 5000 /* size of save_com buffer */ +#define label_offset 2 /* number of levels a label is placed to left + * of code */ + + +#ifndef false +#define false 0 +#endif +#ifndef true +#define true 1 +#endif + +/* + * Exactly one calling file should define this symbol. The global variables + * will be defined in that file, and just referenced elsewhere. + */ +#ifdef DECLARE_INDENT_GLOBALS +#define extern +#endif + +extern FILE *input; /* the fid for the input file */ +extern FILE *output; /* the output file */ + +#define CHECK_SIZE_CODE(desired_size) \ + if (e_code + (desired_size) >= l_code) { \ + int nsize = l_code-s_code + 400 + desired_size; \ + int code_len = e_code-s_code; \ + codebuf = (char *) realloc(codebuf, nsize); \ + if (codebuf == NULL) \ + err(1, NULL); \ + e_code = codebuf + code_len + 1; \ + l_code = codebuf + nsize - 5; \ + s_code = codebuf + 1; \ + } +#define CHECK_SIZE_COM(desired_size) \ + if (e_com + (desired_size) >= l_com) { \ + int nsize = l_com-s_com + 400 + desired_size; \ + int com_len = e_com - s_com; \ + int blank_pos; \ + if (last_bl != NULL) \ + blank_pos = last_bl - combuf; \ + else \ + blank_pos = -1; \ + combuf = (char *) realloc(combuf, nsize); \ + if (combuf == NULL) \ + err(1, NULL); \ + e_com = combuf + com_len + 1; \ + if (blank_pos > 0) \ + last_bl = combuf + blank_pos; \ + l_com = combuf + nsize - 5; \ + s_com = combuf + 1; \ + } +#define CHECK_SIZE_LAB(desired_size) \ + if (e_lab + (desired_size) >= l_lab) { \ + int nsize = l_lab-s_lab + 400 + desired_size; \ + int label_len = e_lab - s_lab; \ + labbuf = (char *) realloc(labbuf, nsize); \ + if (labbuf == NULL) \ + err(1, NULL); \ + e_lab = labbuf + label_len + 1; \ + l_lab = labbuf + nsize - 5; \ + s_lab = labbuf + 1; \ + } +#define CHECK_SIZE_TOKEN(desired_size) \ + if (e_token + (desired_size) >= l_token) { \ + int nsize = l_token-s_token + 400 + desired_size; \ + int token_len = e_token - s_token; \ + tokenbuf = (char *) realloc(tokenbuf, nsize); \ + if (tokenbuf == NULL) \ + err(1, NULL); \ + e_token = tokenbuf + token_len + 1; \ + l_token = tokenbuf + nsize - 5; \ + s_token = tokenbuf + 1; \ + } + +extern char *labbuf; /* buffer for label */ +extern char *s_lab; /* start ... */ +extern char *e_lab; /* .. and end of stored label */ +extern char *l_lab; /* limit of label buffer */ + +extern char *codebuf; /* buffer for code section */ +extern char *s_code; /* start ... */ +extern char *e_code; /* .. and end of stored code */ +extern char *l_code; /* limit of code section */ + +extern char *combuf; /* buffer for comments */ +extern char *s_com; /* start ... */ +extern char *e_com; /* ... and end of stored comments */ +extern char *l_com; /* limit of comment buffer */ + +#define token s_token +extern char *tokenbuf; /* the last token scanned */ +extern char *s_token; +extern char *e_token; +extern char *l_token; + +extern char *in_buffer; /* input buffer */ +extern char *in_buffer_limit; /* the end of the input buffer */ +extern char *buf_ptr; /* ptr to next character to be taken from + * in_buffer */ +extern char *buf_end; /* ptr to first after last char in in_buffer */ + +extern char sc_buf[sc_size]; /* input text is saved here when looking for + * the brace after an if, while, etc */ +extern char *save_com; /* start of the comment stored in sc_buf */ +extern char *sc_end; /* pointer into save_com buffer */ + +extern char *bp_save; /* saved value of buf_ptr when taking input + * from save_com */ +extern char *be_save; /* similarly saved value of buf_end */ + + +extern int found_err; +extern int blanklines_after_declarations; +extern int blanklines_before_blockcomments; +extern int blanklines_after_procs; +extern int blanklines_around_conditional_compilation; +extern int swallow_optional_blanklines; +extern int n_real_blanklines; +extern int prefix_blankline_requested; +extern int postfix_blankline_requested; +extern int break_comma; /* when true and not in parens, break after a + * comma */ +extern int btype_2; /* when true, brace should be on same line as + * if, while, etc */ +extern float case_ind; /* indentation level to be used for a "case + * n:" */ +extern int code_lines; /* count of lines with code */ +extern int had_eof; /* set to true when input is exhausted */ +extern int line_no; /* the current line number. */ +extern int max_col; /* the maximum allowable line length */ +extern int verbose; /* when true, non-essential error messages are + * printed */ +extern int cuddle_else; /* true if else should cuddle up to '}' */ +extern int star_comment_cont; /* true iff comment continuation lines should + * have stars at the beginning of each line. */ +extern int comment_delimiter_on_blankline; +extern int troff; /* true iff were generating troff input */ +extern int procnames_start_line; /* if true, the names of procedures + * being defined get placed in column + * 1 (ie. a newline is placed between + * the type of the procedure and its + * name) */ +extern int proc_calls_space; /* If true, procedure calls look like: + * foo(bar) rather than foo (bar) */ +extern int format_block_comments; /* true if comments beginning with + * `/ * \n' are to be reformatted */ +extern int format_col1_comments; /* If comments which start in column 1 + * are to be magically reformatted + * (just like comments that begin in + * later columns) */ +extern int inhibit_formatting; /* true if INDENT OFF is in effect */ +extern int suppress_blanklines;/* set iff following blanklines should be + * suppressed */ +extern int continuation_indent;/* set to the indentation between the edge of + * code and continuation lines */ +extern int lineup_to_parens; /* if true, continued code within parens will + * be lined up to the open paren */ +extern int lineup_to_parens_always; /* if true, do not attempt to keep + * lined-up code within the margin */ +extern int Bill_Shannon; /* true iff a blank should always be inserted + * after sizeof */ +extern int blanklines_after_declarations_at_proctop; /* This is vaguely + * similar to + * blanklines_after_decla + * rations except that + * it only applies to + * the first set of + * declarations in a + * procedure (just after + * the first '{') and it + * causes a blank line + * to be generated even + * if there are no + * declarations */ +extern int block_comment_max_col; +extern int extra_expression_indent; /* true if continuation lines from the + * expression part of "if(e)", + * "while(e)", "for(e;e;e)" should be + * indented an extra tab stop so that + * they don't conflict with the code + * that follows */ +extern int function_brace_split; /* split function declaration and + * brace onto separate lines */ +extern int use_tabs; /* set true to use tabs for spacing, + * false uses all spaces */ +extern int auto_typedefs; /* set true to recognize identifiers + * ending in "_t" like typedefs */ +extern int space_after_cast; /* "b = (int) a" vs "b = (int)a" */ +extern int postgres_tab_rules; /* use Postgres tab-vs-space rules */ +extern int tabsize; /* the size of a tab */ +extern int else_endif_com_ind; /* the column in which comments to + * the right of #else and #endif + * should start */ + +extern int ifdef_level; + +struct parser_state { + int last_token; + int p_stack[256]; /* this is the parsers stack */ + int il[64]; /* this stack stores indentation levels */ + float cstk[32]; /* used to store case stmt indentation levels */ + int box_com; /* set to true when we are in a "boxed" + * comment. In that case, the first non-blank + * char should be lined up with the / in / followed by * */ + int comment_delta; /* used to set up indentation for all lines + * of a boxed comment after the first one */ + int n_comment_delta;/* remembers how many columns there were + * before the start of a box comment so that + * forthcoming lines of the comment are + * indented properly */ + int cast_mask; /* indicates which close parens potentially + * close off casts */ + int not_cast_mask; /* indicates which close parens definitely + * close off something else than casts */ + int block_init; /* true iff inside a block initialization */ + int block_init_level; /* The level of brace nesting in an + * initialization */ + int last_nl; /* this is true if the last thing scanned was + * a newline */ + int in_or_st; /* Will be true iff there has been a + * declarator (e.g. int or char) and no left + * paren since the last semicolon. When true, + * a '{' is starting a structure definition or + * an initialization list */ + int bl_line; /* set to 1 by dump_line if the line is blank */ + int col_1; /* set to true if the last token started in + * column 1 */ + int com_col; /* this is the column in which the current + * comment should start */ + int com_ind; /* the column in which comments to the right + * of code should start */ + int com_lines; /* the number of lines with comments, set by + * dump_line */ + int dec_nest; /* current nesting level for structure or init */ + int decl_com_ind; /* the column in which comments after + * declarations should be put */ + int decl_on_line; /* set to true if this line of code has part + * of a declaration on it */ + int i_l_follow; /* the level to which ind_level should be set + * after the current line is printed */ + int in_decl; /* set to true when we are in a declaration + * stmt. The processing of braces is then + * slightly different */ + int in_stmt; /* set to 1 while in a stmt */ + int ind_level; /* the current indentation level */ + int ind_size; /* the size of one indentation level */ + int ind_stmt; /* set to 1 if next line should have an extra + * indentation level because we are in the + * middle of a stmt */ + int last_u_d; /* set to true after scanning a token which + * forces a following operator to be unary */ + int leave_comma; /* if true, never break declarations after + * commas */ + int ljust_decl; /* true if declarations should be left + * justified */ + int out_coms; /* the number of comments processed, set by + * pr_comment */ + int out_lines; /* the number of lines written, set by + * dump_line */ + int p_l_follow; /* used to remember how to indent following + * statement */ + int paren_level; /* parenthesization level. used to indent + * within statements */ + short paren_indents[20]; /* column positions of each paren */ + int pcase; /* set to 1 if the current line label is a + * case. It is printed differently from a + * regular label */ + int search_brace; /* set to true by parse when it is necessary + * to buffer up all info up to the start of a + * stmt after an if, while, etc */ + int unindent_displace; /* comments not to the right of code + * will be placed this many + * indentation levels to the left of + * code */ + int use_ff; /* set to one if the current line should be + * terminated with a form feed */ + int want_blank; /* set to true when the following token should + * be prefixed by a blank. (Said prefixing is + * ignored in some cases.) */ + int else_if; /* True iff else if pairs should be handled + * specially */ + int decl_indent; /* column to indent declared identifiers to */ + int local_decl_indent; /* like decl_indent but for locals */ + int keyword; /* the type of a keyword or 0 */ + int dumped_decl_indent; + float case_indent; /* The distance to indent case labels from the + * switch statement */ + int in_parameter_declaration; + int indent_parameters; + int tos; /* pointer to top of stack */ + char procname[100]; /* The name of the current procedure */ + int just_saw_decl; +}; + +extern struct parser_state ps; +extern struct parser_state state_stack[5]; +extern struct parser_state match_state[5]; + +/* Undo previous hackery */ +#ifdef DECLARE_INDENT_GLOBALS +#undef extern +#endif diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c new file mode 100644 index 0000000000..3ce8bfb70c --- /dev/null +++ b/src/tools/pg_bsd_indent/io.c @@ -0,0 +1,608 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent.h" + +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 +dump_line(void) +{ /* dump_line is the routine that actually + * effects the printing of the new source. It + * prints the label section, followed by the + * code section with the appropriate nesting + * level, followed by any comments */ + int cur_col, + target_col = 1; + static int not_first_line; + + if (ps.procname[0]) { + ps.ind_level = 0; + ps.procname[0] = 0; + } + if (s_code == e_code && s_lab == e_lab && s_com == e_com) { + if (suppress_blanklines > 0) + suppress_blanklines--; + else { + ps.bl_line = true; + n_real_blanklines++; + } + } + else if (!inhibit_formatting) { + suppress_blanklines = 0; + ps.bl_line = false; + if (prefix_blankline_requested && not_first_line) { + if (swallow_optional_blanklines) { + if (n_real_blanklines == 1) + n_real_blanklines = 0; + } + else { + if (n_real_blanklines == 0) + n_real_blanklines = 1; + } + } + while (--n_real_blanklines >= 0) + putc('\n', output); + n_real_blanklines = 0; + if (ps.ind_level == 0) + ps.ind_stmt = 0; /* this is a class A kludge. dont do + * additional statement indentation if we are + * at bracket level 0 */ + + if (e_lab != s_lab || e_code != s_code) + ++code_lines; /* keep count of lines with code */ + + + if (e_lab != s_lab) { /* print lab, if any */ + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t')) + e_lab--; + *e_lab = '\0'; + cur_col = pad_output(1, compute_label_target()); + if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0 + || strncmp(s_lab, "#endif", 6) == 0)) { + char *s = s_lab; + if (e_lab[-1] == '\n') e_lab--; + do putc(*s++, output); + while (s < e_lab && 'a' <= *s && *s<='z'); + while ((*s == ' ' || *s == '\t') && s < e_lab) + s++; + if (s < e_lab) + fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */", + (int)(e_lab - s), s); + } + else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab); + cur_col = count_spaces(cur_col, s_lab); + } + else + cur_col = 1; /* there is no label section */ + + ps.pcase = false; + + if (s_code != e_code) { /* print code section, if any */ + char *p; + + if (comment_open) { + comment_open = 0; + fprintf(output, ".*/\n"); + } + target_col = compute_code_target(); + { + int i; + + for (i = 0; i < ps.p_l_follow; i++) + if (ps.paren_indents[i] >= 0) + ps.paren_indents[i] = -(ps.paren_indents[i] + target_col); + } + cur_col = pad_output(cur_col, target_col); + for (p = s_code; p < e_code; p++) + if (*p == (char) 0200) + fprintf(output, "%d", target_col * 7); + else + putc(*p, output); + cur_col = count_spaces(cur_col, s_code); + } + if (s_com != e_com) { /* print comment, if any */ + int target = ps.com_col; + char *com_st = s_com; + + target += ps.comment_delta; + while (*com_st == '\t') /* consider original indentation in + * case this is a box comment */ + com_st++, target += tabsize; + while (target <= 0) + if (*com_st == ' ') + target++, com_st++; + else if (*com_st == '\t') + target = tabsize * (1 + (target - 1) / tabsize) + 1, com_st++; + else + target = 1; + if (cur_col > target) { /* if comment can't fit on this line, + * put it on next line */ + putc('\n', output); + cur_col = 1; + ++ps.out_lines; + } + while (e_com > com_st && isspace((unsigned char)e_com[-1])) + e_com--; + (void)pad_output(cur_col, target); + fwrite(com_st, e_com - com_st, 1, output); + ps.comment_delta = ps.n_comment_delta; + ++ps.com_lines; /* count lines with comments */ + } + if (ps.use_ff) + putc('\014', output); + else + putc('\n', output); + ++ps.out_lines; + if (ps.just_saw_decl == 1 && blanklines_after_declarations) { + prefix_blankline_requested = 1; + ps.just_saw_decl = 0; + } + else + prefix_blankline_requested = postfix_blankline_requested; + postfix_blankline_requested = 0; + } + ps.decl_on_line = ps.in_decl; /* if we are in the middle of a + * declaration, remember that fact for + * proper comment indentation */ + ps.ind_stmt = ps.in_stmt & ~ps.in_decl; /* next line should be + * indented if we have not + * completed this stmt and if + * we are not in the middle of + * a declaration */ + ps.use_ff = false; + ps.dumped_decl_indent = 0; + *(e_lab = s_lab) = '\0'; /* reset buffers */ + *(e_code = s_code) = '\0'; + *(e_com = s_com = combuf + 1) = '\0'; + ps.ind_level = ps.i_l_follow; + ps.paren_level = ps.p_l_follow; + if (ps.paren_level > 0) + paren_target = -ps.paren_indents[ps.paren_level - 1]; + not_first_line = 1; +} + +int +compute_code_target(void) +{ + int target_col = ps.ind_size * ps.ind_level + 1; + + if (ps.paren_level) + if (!lineup_to_parens) + target_col += continuation_indent + * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level); + else if (lineup_to_parens_always) + target_col = paren_target; + else { + int w; + int t = paren_target; + + if ((w = count_spaces(t, s_code) - max_col) > 0 + && count_spaces(target_col, s_code) <= max_col) { + t -= w + 1; + if (t > target_col) + target_col = t; + } + else + target_col = t; + } + else if (ps.ind_stmt) + target_col += continuation_indent; + return target_col; +} + +int +compute_label_target(void) +{ + return + ps.pcase ? (int) (case_ind * ps.ind_size) + 1 + : *s_lab == '#' ? 1 + : 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 + * + * All rights reserved + * + * + * NAME: fill_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 + * buffer from temporary buffer + * + */ +void +fill_buffer(void) +{ /* this routine reads stuff from the input */ + char *p; + int i; + FILE *f = input; + + if (bp_save != NULL) { /* there is a partly filled input buffer left */ + 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 */ + } + for (p = in_buffer;;) { + if (p >= in_buffer_limit) { + int size = (in_buffer_limit - in_buffer) * 2 + 10; + int offset = p - in_buffer; + in_buffer = realloc(in_buffer, size); + if (in_buffer == NULL) + errx(1, "input line too long"); + p = in_buffer + offset; + in_buffer_limit = in_buffer + size - 2; + } + 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; + } + buf_ptr = in_buffer; + buf_end = p; + if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') { + if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0) + fill_buffer(); /* flush indent error message */ + else { + int com = 0; + + p = in_buffer; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '/' && p[1] == '*') { + p += 2; + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E' + && p[4] == 'N' && p[5] == 'T') { + p += 6; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '*') + com = 1; + else if (*p == 'O') { + if (*++p == 'N') + p++, com = 1; + else if (*p == 'F' && *++p == 'F') + p++, com = 2; + } + while (*p == ' ' || *p == '\t') + p++; + if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) { + if (s_com != e_com || s_lab != e_lab || s_code != e_code) + dump_line(); + if (!(inhibit_formatting = com - 1)) { + n_real_blanklines = 0; + postfix_blankline_requested = 0; + prefix_blankline_requested = 0; + suppress_blanklines = 1; + } + } + } + } + } + } + if (inhibit_formatting) { + p = in_buffer; + do + putc(*p, output); + while (*p++ != '\n'); + } +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: pad_output + * + * FUNCTION: Writes tabs and spaces to move the current column up to the desired + * position. + * + * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. + * + * PARAMETERS: current integer The current column + * target integer The desired column + * + * RETURNS: Integer value of the new column. (If current >= target, no action is + * taken, and current is returned. + * + * GLOBALS: None + * + * CALLS: write (sys) + * + * CALLED BY: dump_line + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +static int +pad_output(int current, int target) + /* writes tabs and blanks (if necessary) to + * get the current output position up to the + * target column */ + /* current: the current column value */ + /* target: position we want it at */ +{ + int curr; /* internal column pointer */ + + if (current >= target) + return (current); /* line is already long enough */ + curr = current; + if (use_tabs) { + int tcur; + + while ((tcur = tabsize * (1 + (curr - 1) / tabsize) + 1) <= target) { + putc((!postgres_tab_rules || + tcur != curr + 1 || + target >= tcur + tabsize) ? '\t' : ' ', output); + curr = tcur; + } + } + while (curr++ < target) + putc(' ', output); /* pad with final blanks */ + + return (target); +} + +/* + * Copyright (C) 1976 by the Board of Trustees of the University of Illinois + * + * All rights reserved + * + * + * NAME: count_spaces + * + * FUNCTION: Find out where printing of a given string will leave the current + * character position on output. + * + * ALGORITHM: Run thru input string and add appropriate values to current + * position. + * + * RETURNS: Integer value of position after printing "buffer" starting in column + * "current". + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +int +count_spaces_until(int cur, char *buffer, char *end) +/* + * this routine figures out where the character position will be after + * printing the text in buffer starting at column "current" + */ +{ + char *buf; /* used to look thru buffer */ + + for (buf = buffer; *buf != '\0' && buf != end; ++buf) { + switch (*buf) { + + case '\n': + case 014: /* form feed */ + cur = 1; + break; + + case '\t': + cur = tabsize * (1 + (cur - 1) / tabsize) + 1; + break; + + case 010: /* backspace */ + --cur; + break; + + default: + ++cur; + break; + } /* end of switch */ + } /* end of for loop */ + return (cur); +} + +int +count_spaces(int cur, char *buffer) +{ + return (count_spaces_until(cur, buffer, NULL)); +} + +void +diag4(int level, const char *msg, int a, int b) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a, b); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a, b); + fprintf(stderr, "\n"); + } +} + +void +diag3(int level, const char *msg, int a) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, msg, a); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, msg, a); + fprintf(stderr, "\n"); + } +} + +void +diag2(int level, const char *msg) +{ + if (level) + found_err = 1; + if (output == stdout) { + fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stdout, "%s", msg); + fprintf(stdout, " */\n"); + } + else { + fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); + fprintf(stderr, "%s", msg); + fprintf(stderr, "\n"); + } +} + diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c new file mode 100644 index 0000000000..f01596a870 --- /dev/null +++ b/src/tools/pg_bsd_indent/lexi.c @@ -0,0 +1,724 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +/* + * Here we have the token scanner for indent. It scans off one token and puts + * it in the global variable "token". It returns a code, indicating the type + * of token scanned. + */ + +#include <err.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +#define alphanum 1 +#ifdef undef +#define opchar 3 +#endif + +struct templ { + const char *rwd; + int rwcode; +}; + +/* + * This table has to be sorted alphabetically, because it'll be used in binary + * search. For the same reason, string must be the first thing in struct templ. + */ +struct templ specials[] = +{ + {"_Bool", 4}, + {"_Complex", 4}, + {"_Imaginary", 4}, + {"auto", 10}, + {"bool", 4}, + {"break", 9}, + {"case", 8}, + {"char", 4}, + {"complex", 4}, + {"const", 4}, + {"continue", 12}, + {"default", 8}, + {"do", 6}, + {"double", 4}, + {"else", 6}, + {"enum", 3}, + {"extern", 10}, + {"float", 4}, + {"for", 5}, + {"global", 4}, + {"goto", 9}, + {"if", 5}, + {"imaginary", 4}, + {"inline", 12}, + {"int", 4}, + {"long", 4}, + {"offsetof", 1}, + {"register", 10}, + {"restrict", 12}, + {"return", 9}, + {"short", 4}, + {"signed", 4}, + {"sizeof", 2}, + {"static", 10}, + {"struct", 3}, + {"switch", 7}, + {"typedef", 11}, + {"union", 3}, + {"unsigned", 4}, + {"void", 4}, + {"volatile", 4}, + {"while", 5} +}; + +const char **typenames; +int typename_count; +int typename_top = -1; + +char chartype[128] = +{ /* this is used to facilitate the decision of + * what type (alphanumeric, operator) each + * character is */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 1, 3, 3, 0, + 0, 0, 3, 3, 0, 3, 0, 3, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 0, 3, 3, 3, 3, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 3, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 0, 3, 0 +}; + +static int +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) +{ + int unary_delim; /* this is set to 1 if the current token + * forces a following operator to be unary */ + int code; /* internal code to be returned */ + char qchar; /* the delimiter character for a string */ + + e_token = s_token; /* point to start of place to save token */ + unary_delim = false; + state->col_1 = state->last_nl; /* tell world that this token started + * in column 1 iff the last thing + * scanned was a newline */ + state->last_nl = false; + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + state->col_1 = false; /* leading blanks imply token is not in column + * 1 */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + + /* Scan an alphanumeric token */ + if (chartype[*buf_ptr & 127] == alphanum || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + /* + * we have a character or number + */ + struct templ *p; + + if (isdigit((unsigned char)*buf_ptr) || + (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) { + int seendot = 0, + seenexp = 0, + seensfx = 0; + + /* + * base 2, base 8, base 16: + */ + if (buf_ptr[0] == '0' && buf_ptr[1] != '.') { + int len; + + if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B') + len = strspn(buf_ptr + 2, "01") + 2; + else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X') + len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2; + else + len = strspn(buf_ptr + 1, "012345678") + 1; + if (len > 0) { + CHECK_SIZE_TOKEN(len); + memcpy(e_token, buf_ptr, len); + e_token += len; + buf_ptr += len; + } + else + diag2(1, "Unterminated literal"); + } + else /* base 10: */ + while (1) { + if (*buf_ptr == '.') { + if (seendot) + break; + else + seendot++; + } + CHECK_SIZE_TOKEN(3); + *e_token++ = *buf_ptr++; + if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') { + if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) + break; + else { + seenexp++; + seendot++; + *e_token++ = *buf_ptr++; + if (*buf_ptr == '+' || *buf_ptr == '-') + *e_token++ = *buf_ptr++; + } + } + } + + while (1) { + CHECK_SIZE_TOKEN(2); + if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) { + *e_token++ = *buf_ptr++; + seensfx |= 1; + continue; + } + if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) { + if (buf_ptr[1] == buf_ptr[0]) + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; + seensfx |= 2; + continue; + } + break; + } + } + else + while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) { + /* fill_buffer() terminates buffer with newline */ + if (*buf_ptr == BACKSLASH) { + if (*(buf_ptr + 1) == '\n') { + buf_ptr += 2; + if (buf_ptr >= buf_end) + fill_buffer(); + } else + break; + } + CHECK_SIZE_TOKEN(1); + /* copy it over */ + *e_token++ = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + } + *e_token = '\0'; + + if (s_token[0] == 'L' && s_token[1] == '\0' && + (*buf_ptr == '"' || *buf_ptr == '\'')) + return (strpfx); + + while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ + if (++buf_ptr >= buf_end) + fill_buffer(); + } + state->keyword = 0; + if (state->last_token == structure && !state->p_l_follow) { + /* if last token was 'struct' and we're not + * in parentheses, then this token + * should be treated as a declaration */ + state->last_u_d = true; + return (decl); + } + /* + * Operator after identifier is binary unless last token was 'struct' + */ + state->last_u_d = (state->last_token == structure); + + p = bsearch(s_token, + specials, + sizeof(specials) / sizeof(specials[0]), + sizeof(specials[0]), + strcmp_type); + if (p == NULL) { /* not a special keyword... */ + char *u; + + /* ... so maybe a type_t or a typedef */ + if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) && + strcmp(u, "_t") == 0) || (typename_top >= 0 && + bsearch(s_token, typenames, typename_top + 1, + sizeof(typenames[0]), strcmp_type))) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + goto found_typename; + } + } else { /* we have a keyword */ + state->keyword = p->rwcode; + state->last_u_d = true; + switch (p->rwcode) { + case 7: /* it is a switch */ + return (swstmt); + case 8: /* a case or default */ + return (casestmt); + + case 3: /* a "struct" */ + /* FALLTHROUGH */ + case 4: /* one of the declaration keywords */ + found_typename: + if (state->p_l_follow) { + /* inside parens: cast, param list, offsetof or sizeof */ + state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask; + } + if (state->last_token == period || state->last_token == unary_op) { + state->keyword = 0; + break; + } + if (p != NULL && p->rwcode == 3) + return (structure); + if (state->p_l_follow) + break; + return (decl); + + case 5: /* if, while, for */ + return (sp_paren); + + case 6: /* do, else */ + return (sp_nparen); + + case 10: /* storage class specifier */ + return (storage); + + case 11: /* typedef */ + return (type_def); + + default: /* all others are treated like any other + * identifier */ + return (ident); + } /* end of switch */ + } /* end of if (found_it) */ + if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 && + state->in_parameter_declaration == 0 && state->block_init == 0) { + 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 + * token is in fact a declaration keyword -- one that has been + * typedefd + */ + else if (!state->p_l_follow && !state->block_init && + !state->in_stmt && + ((*buf_ptr == '*' && buf_ptr[1] != '=') || + isalpha((unsigned char)*buf_ptr)) && + (state->last_token == semicolon || state->last_token == lbrace || + state->last_token == rbrace)) { + state->keyword = 4; /* a type name */ + state->last_u_d = true; + return decl; + } + if (state->last_token == decl) /* if this is a declared variable, + * then following sign is unary */ + state->last_u_d = true; /* will make "int a -1" work */ + return (ident); /* the ident is not in the list */ + } /* end of processing for alphanum character */ + + /* Scan a non-alphanumeric token */ + + CHECK_SIZE_TOKEN(3); /* things like "<<=" */ + *e_token++ = *buf_ptr; /* if it is only a one-character token, it is + * moved here */ + *e_token = '\0'; + if (++buf_ptr >= buf_end) + fill_buffer(); + + switch (*token) { + case '\n': + unary_delim = state->last_u_d; + state->last_nl = true; /* remember that we just had a newline */ + code = (had_eof ? 0 : newline); + + /* + * if data has been exhausted, the newline is a dummy, and we should + * return code to stop + */ + break; + + case '\'': /* start of quoted character */ + case '"': /* start of string */ + qchar = *token; + do { /* copy the string */ + while (1) { /* move one character or [/<char>]<char> */ + if (*buf_ptr == '\n') { + diag2(1, "Unterminated literal"); + goto stop_lit; + } + CHECK_SIZE_TOKEN(2); + *e_token = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_token == BACKSLASH) { /* if escape, copy extra char */ + if (*buf_ptr == '\n') /* check for escaped newline */ + ++line_no; + *++e_token = *buf_ptr++; + ++e_token; /* we must increment this again because we + * copied two chars */ + if (buf_ptr >= buf_end) + fill_buffer(); + } + else + break; /* we copied one character */ + } /* end of while (1) */ + } while (*e_token++ != qchar); +stop_lit: + code = ident; + break; + + case ('('): + case ('['): + unary_delim = true; + code = lparen; + break; + + case (')'): + case (']'): + code = rparen; + break; + + case '#': + unary_delim = state->last_u_d; + code = preesc; + break; + + case '?': + unary_delim = true; + code = question; + break; + + case (':'): + code = colon; + unary_delim = true; + break; + + case (';'): + unary_delim = true; + code = semicolon; + break; + + case ('{'): + unary_delim = true; + + /* + * if (state->in_or_st) state->block_init = 1; + */ + /* ? code = state->block_init ? lparen : lbrace; */ + code = lbrace; + break; + + case ('}'): + unary_delim = true; + /* ? code = state->block_init ? rparen : rbrace; */ + code = rbrace; + break; + + case 014: /* a form feed */ + unary_delim = state->last_u_d; + state->last_nl = true; /* remember this so we can set 'state->col_1' + * right */ + code = form_feed; + break; + + case (','): + unary_delim = true; + code = comma; + break; + + case '.': + unary_delim = false; + code = period; + break; + + case '-': + case '+': /* check for -, +, --, ++ */ + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + if (*buf_ptr == token[0]) { + /* check for doubled character */ + *e_token++ = *buf_ptr++; + /* buffer overflow will be checked at end of loop */ + if (state->last_token == ident || state->last_token == rparen) { + code = (state->last_u_d ? unary_op : postop); + /* check for following ++ or -- */ + unary_delim = false; + } + } + else if (*buf_ptr == '=') + /* check for operator += */ + *e_token++ = *buf_ptr++; + else if (*buf_ptr == '>') { + /* check for operator -> */ + *e_token++ = *buf_ptr++; + unary_delim = false; + code = unary_op; + state->want_blank = false; + } + break; /* buffer overflow will be checked at end of + * switch */ + + case '=': + if (state->in_or_st) + state->block_init = 1; +#ifdef undef + if (chartype[*buf_ptr & 127] == opchar) { /* we have two char assignment */ + e_token[-1] = *buf_ptr++; + if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) + *e_token++ = *buf_ptr++; + *e_token++ = '='; /* Flip =+ to += */ + *e_token = 0; + } +#else + if (*buf_ptr == '=') {/* == */ + *e_token++ = '='; /* Flip =+ to += */ + buf_ptr++; + *e_token = 0; + } +#endif + code = binary_op; + unary_delim = true; + break; + /* can drop thru!!! */ + + case '>': + case '<': + case '!': /* ops like <, <<, <=, !=, etc */ + if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + break; + + case '*': + unary_delim = true; + if (!state->last_u_d) { + if (*buf_ptr == '=') + *e_token++ = *buf_ptr++; + code = binary_op; + break; + } + while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) { + if (*buf_ptr == '*') { + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + } + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = unary_op; + break; + + default: + if (token[0] == '/' && *buf_ptr == '*') { + /* it is start of comment */ + *e_token++ = '*'; + + if (++buf_ptr >= buf_end) + fill_buffer(); + + code = comment; + unary_delim = state->last_u_d; + break; + } + while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { + /* + * handle ||, &&, etc, and also things as in int *****i + */ + CHECK_SIZE_TOKEN(1); + *e_token++ = *buf_ptr; + if (++buf_ptr >= buf_end) + fill_buffer(); + } + code = (state->last_u_d ? unary_op : binary_op); + unary_delim = true; + + + } /* end of switch */ + if (buf_ptr >= buf_end) /* check for input buffer empty */ + fill_buffer(); + state->last_u_d = unary_delim; + CHECK_SIZE_TOKEN(1); + *e_token = '\0'; /* null terminate the token */ + return (code); +} + +void +alloc_typenames(void) +{ + + typenames = (const char **)malloc(sizeof(typenames[0]) * + (typename_count = 16)); + if (typenames == NULL) + err(1, NULL); +} + +void +add_typename(const char *key) +{ + int comparison; + const char *copy; + + if (typename_top + 1 >= typename_count) { + typenames = realloc((void *)typenames, + sizeof(typenames[0]) * (typename_count *= 2)); + if (typenames == NULL) + err(1, NULL); + } + if (typename_top == -1) + typenames[++typename_top] = copy = strdup(key); + else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) { + /* take advantage of sorted input */ + if (comparison == 0) /* remove duplicates */ + return; + typenames[++typename_top] = copy = strdup(key); + } + else { + int p; + + for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++) + /* find place for the new key */; + if (comparison == 0) /* remove duplicates */ + return; + memmove(&typenames[p + 1], &typenames[p], + sizeof(typenames[0]) * (++typename_top - p)); + typenames[p] = copy = strdup(key); + } + + if (copy == NULL) + err(1, NULL); +} diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c new file mode 100644 index 0000000000..bf6b1697f9 --- /dev/null +++ b/src/tools/pg_bsd_indent/parse.c @@ -0,0 +1,342 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" + +static void reduce(void); + +void +parse(int tk) /* tk: the code for the construct scanned */ +{ + int i; + +#ifdef debug + printf("%2d - %s\n", tk, token); +#endif + + while (ps.p_stack[ps.tos] == ifhead && tk != elselit) { + /* true if we have an if without an else */ + ps.p_stack[ps.tos] = stmt; /* apply the if(..) stmt ::= stmt + * reduction */ + reduce(); /* see if this allows any reduction */ + } + + + switch (tk) { /* go on and figure out what to do with the + * input */ + + case decl: /* scanned a declaration word */ + ps.search_brace = btype_2; + /* indicate that following brace should be on same line */ + if (ps.p_stack[ps.tos] != decl) { /* only put one declaration + * onto stack */ + break_comma = true; /* while in declaration, newline should be + * forced after comma */ + ps.p_stack[++ps.tos] = decl; + ps.il[ps.tos] = ps.i_l_follow; + + if (ps.ljust_decl) {/* only do if we want left justified + * declarations */ + ps.ind_level = 0; + for (i = ps.tos - 1; i > 0; --i) + if (ps.p_stack[i] == decl) + ++ps.ind_level; /* indentation is number of + * declaration levels deep we are */ + ps.i_l_follow = ps.ind_level; + } + } + break; + + case ifstmt: /* scanned if (...) */ + if (ps.p_stack[ps.tos] == elsehead && ps.else_if) /* "else if ..." */ + /* + * Note that the stack pointer here is decremented, effectively + * reducing "else if" to "if". This saves a lot of stack space + * in case of a long "if-else-if ... else-if" sequence. + */ + ps.i_l_follow = ps.il[ps.tos--]; + /* the rest is the same as for dolit and forstmt */ + /* FALLTHROUGH */ + case dolit: /* 'do' */ + case forstmt: /* for (...) */ + ps.p_stack[++ps.tos] = tk; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + ++ps.i_l_follow; /* subsequent statements should be indented 1 */ + ps.search_brace = btype_2; + break; + + case lbrace: /* scanned { */ + break_comma = false; /* don't break comma in an initial list */ + if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl + || ps.p_stack[ps.tos] == stmtl) + ++ps.i_l_follow; /* it is a random, isolated stmt group or a + * declaration */ + else { + if (s_code == e_code) { + /* + * only do this if there is nothing on the line + */ + --ps.ind_level; + /* + * it is a group as part of a while, for, etc. + */ + if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1) + --ps.ind_level; + /* + * for a switch, brace should be two levels out from the code + */ + } + } + + ps.p_stack[++ps.tos] = lbrace; + ps.il[ps.tos] = ps.ind_level; + ps.p_stack[++ps.tos] = stmt; + /* allow null stmt between braces */ + ps.il[ps.tos] = ps.i_l_follow; + break; + + case whilestmt: /* scanned while (...) */ + if (ps.p_stack[ps.tos] == dohead) { + /* it is matched with do stmt */ + ps.ind_level = ps.i_l_follow = ps.il[ps.tos]; + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.ind_level = ps.i_l_follow; + } + else { /* it is a while loop */ + ps.p_stack[++ps.tos] = whilestmt; + ps.il[ps.tos] = ps.i_l_follow; + ++ps.i_l_follow; + ps.search_brace = btype_2; + } + + break; + + case elselit: /* scanned an else */ + + if (ps.p_stack[ps.tos] != ifhead) + diag2(1, "Unmatched 'else'"); + else { + ps.ind_level = ps.il[ps.tos]; /* indentation for else should + * be same as for if */ + ps.i_l_follow = ps.ind_level + 1; /* everything following should + * be in 1 level */ + ps.p_stack[ps.tos] = elsehead; + /* remember if with else */ + ps.search_brace = btype_2 | ps.else_if; + } + break; + + case rbrace: /* scanned a } */ + /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */ + if (ps.tos > 0 && ps.p_stack[ps.tos - 1] == lbrace) { + ps.ind_level = ps.i_l_follow = ps.il[--ps.tos]; + ps.p_stack[ps.tos] = stmt; + } + else + diag2(1, "Statement nesting error"); + break; + + case swstmt: /* had switch (...) */ + ps.p_stack[++ps.tos] = swstmt; + ps.cstk[ps.tos] = case_ind; + /* save current case indent level */ + ps.il[ps.tos] = ps.i_l_follow; + case_ind = ps.i_l_follow + ps.case_indent; /* cases should be one + * level down from + * switch */ + ps.i_l_follow += ps.case_indent + 1; /* statements should be two + * levels in */ + ps.search_brace = btype_2; + break; + + case semicolon: /* this indicates a simple stmt */ + break_comma = false; /* turn off flag to break after commas in a + * declaration */ + ps.p_stack[++ps.tos] = stmt; + ps.il[ps.tos] = ps.ind_level; + break; + + default: /* this is an error */ + diag2(1, "Unknown code to parser"); + return; + + + } /* end of switch */ + + if (ps.tos >= nitems(ps.p_stack) - 1) + errx(1, "Parser stack overflow"); + + reduce(); /* see if any reduction can be done */ + +#ifdef debug + for (i = 1; i <= ps.tos; ++i) + printf("(%d %d)", ps.p_stack[i], ps.il[i]); + printf("\n"); +#endif + + return; +} + +/* + * NAME: reduce + * + * FUNCTION: Implements the reduce part of the parsing algorithm + * + * ALGORITHM: The following reductions are done. Reductions are repeated + * until no more are possible. + * + * Old TOS New TOS + * <stmt> <stmt> <stmtl> + * <stmtl> <stmt> <stmtl> + * do <stmt> "dostmt" + * if <stmt> "ifstmt" + * switch <stmt> <stmt> + * decl <stmt> <stmt> + * "ifelse" <stmt> <stmt> + * for <stmt> <stmt> + * while <stmt> <stmt> + * "dostmt" while <stmt> + * + * On each reduction, ps.i_l_follow (the indentation for the following line) + * is set to the indentation level associated with the old TOS. + * + * PARAMETERS: None + * + * RETURNS: Nothing + * + * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = + * + * CALLS: None + * + * CALLED BY: parse + * + * HISTORY: initial coding November 1976 D A Willcox of CAC + * + */ +/*----------------------------------------------*\ +| REDUCTION PHASE | +\*----------------------------------------------*/ +static void +reduce(void) +{ + int i; + + for (;;) { /* keep looping until there is nothing left to + * reduce */ + + switch (ps.p_stack[ps.tos]) { + + case stmt: + switch (ps.p_stack[ps.tos - 1]) { + + case stmt: + case stmtl: + /* stmtl stmt or stmt stmt */ + ps.p_stack[--ps.tos] = stmtl; + break; + + case dolit: /* <do> <stmt> */ + ps.p_stack[--ps.tos] = dohead; + ps.i_l_follow = ps.il[ps.tos]; + break; + + case ifstmt: + /* <if> <stmt> */ + ps.p_stack[--ps.tos] = ifhead; + for (i = ps.tos - 1; + ( + ps.p_stack[i] != stmt + && + ps.p_stack[i] != stmtl + && + ps.p_stack[i] != lbrace + ); + --i); + ps.i_l_follow = ps.il[i]; + /* + * for the time being, we will assume that there is no else on + * this if, and set the indentation level accordingly. If an + * else is scanned, it will be fixed up later + */ + break; + + case swstmt: + /* <switch> <stmt> */ + case_ind = ps.cstk[ps.tos - 1]; + /* FALLTHROUGH */ + case decl: /* finish of a declaration */ + case elsehead: + /* <<if> <stmt> else> <stmt> */ + case forstmt: + /* <for> <stmt> */ + case whilestmt: + /* <while> <stmt> */ + ps.p_stack[--ps.tos] = stmt; + ps.i_l_follow = ps.il[ps.tos]; + break; + + default: /* <anything else> <stmt> */ + return; + + } /* end of section for <stmt> on top of stack */ + break; + + case whilestmt: /* while (...) on top */ + if (ps.p_stack[ps.tos - 1] == dohead) { + /* it is termination of a do while */ + ps.tos -= 2; + break; + } + else + return; + + default: /* anything else on top */ + return; + + } + } +} diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c new file mode 100644 index 0000000000..b0eacac1bb --- /dev/null +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 1985 Sun Microsystems, Inc. + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)pr_comment.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif + +#include "c.h" + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "indent_globs.h" +#include "indent_codes.h" +#include "indent.h" +/* + * NAME: + * pr_comment + * + * FUNCTION: + * This routine takes care of scanning and printing comments. + * + * ALGORITHM: + * 1) Decide where the comment should be aligned, and if lines should + * be broken. + * 2) If lines should not be broken and filled, just copy up to end of + * comment. + * 3) If lines should be filled, then scan thru input_buffer copying + * characters to com_buf. Remember where the last blank, tab, or + * newline was. When line is filled, print up to last blank and + * continue copying. + * + * HISTORY: + * November 1976 D A Willcox of CAC Initial coding + * 12/6/76 D A Willcox of CAC Modification to handle + * UNIX-style comments + * + */ + +/* + * this routine processes comments. It makes an attempt to keep comments from + * going over the max line length. If a line is too long, it moves everything + * from the last blank to the next comment line. Blanks and tabs from the + * beginning of the input line are removed + */ + +void +pr_comment(void) +{ + int now_col; /* column we are in now */ + int adj_max_col; /* Adjusted max_col for when we decide to + * spill comments over the right margin */ + char *last_bl; /* points to the last blank in the output + * buffer */ + char *t_ptr; /* used for moving string */ + int break_delim = comment_delimiter_on_blankline; + int l_just_saw_decl = ps.just_saw_decl; + adj_max_col = max_col; + ps.just_saw_decl = 0; + last_bl = NULL; /* no blanks found so far */ + ps.box_com = false; /* at first, assume that we are not in + * a boxed comment or some other + * comment that should not be touched */ + ++ps.out_coms; /* keep track of number of comments */ + + /* Figure where to align and how to treat the comment */ + + if (ps.col_1 && !format_col1_comments) { /* if comment starts in column + * 1 it should not be touched */ + ps.box_com = true; + break_delim = false; + ps.com_col = 1; + } + else { + if (*buf_ptr == '-' || *buf_ptr == '*' || + (*buf_ptr == '\n' && !format_block_comments)) { + ps.box_com = true; /* A comment with a '-' or '*' immediately + * after the /+* is assumed to be a boxed + * comment. A comment with a newline + * immediately after the /+* is assumed to + * be a block comment and is treated as a + * box comment unless format_block_comments + * is nonzero (the default). */ + break_delim = false; + } + if ( /* ps.bl_line && */ (s_lab == e_lab) && (s_code == e_code)) { + /* klg: check only if this line is blank */ + /* + * If this (*and previous lines are*) blank, dont put comment way + * out at left + */ + ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; + adj_max_col = block_comment_max_col; + if (ps.com_col <= 1) + ps.com_col = 1 + !format_col1_comments; + } + else { + int target_col; + break_delim = false; + if (s_code != e_code) + target_col = count_spaces(compute_code_target(), s_code); + else { + target_col = 1; + if (s_lab != e_lab) + target_col = count_spaces(compute_label_target(), s_lab); + } + if (s_lab != e_lab && s_lab[1] == 'e' && + (strncmp(s_lab, "#endif", 6) == 0 || + strncmp(s_lab, "#else", 5) == 0)) + ps.com_col = else_endif_com_ind <= target_col + ? target_col + 1 : else_endif_com_ind; + else + ps.com_col = ps.decl_on_line || ps.ind_level == 0 + ? ps.decl_com_ind : ps.com_ind; + if (ps.com_col <= target_col) + ps.com_col = tabsize * (1 + (target_col - 1) / tabsize) + 1; + if (ps.com_col + 24 > adj_max_col) + adj_max_col = ps.com_col + 24; + } + } + if (ps.box_com) { + /* + * Find out how much indentation there was originally, because that + * much will have to be ignored by pad_output() in dump_line(). This + * is a box comment, so nothing changes -- not even indentation. + * + * The comment we're about to read usually comes from in_buffer, + * unless it has been copied into save_com. + */ + char *start; + + start = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? + sc_buf : in_buffer; + ps.n_comment_delta = 1 - count_spaces_until(1, start, buf_ptr - 2); + } + else { + ps.n_comment_delta = 0; + while (*buf_ptr == ' ' || *buf_ptr == '\t') + buf_ptr++; + } + ps.comment_delta = 0; + *e_com++ = '/'; /* put '/' followed by '*' into buffer */ + *e_com++ = '*'; + if (*buf_ptr != ' ' && !ps.box_com) + *e_com++ = ' '; + + /* + * Don't put a break delimiter if this is a one-liner that won't wrap. + */ + if (break_delim) + for (t_ptr = buf_ptr; *t_ptr != '\0' && *t_ptr != '\n'; t_ptr++) { + if (t_ptr >= buf_end) + fill_buffer(); + if (t_ptr[0] == '*' && t_ptr[1] == '/') { + if (adj_max_col >= count_spaces_until(ps.com_col, buf_ptr, t_ptr + 2)) + break_delim = false; + break; + } + } + + if (break_delim) { + char *t = e_com; + e_com = s_com + 2; + *e_com = 0; + if (blanklines_before_blockcomments && ps.last_token != lbrace) + prefix_blankline_requested = 1; + dump_line(); + e_com = s_com = t; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + + /* Start to copy the comment */ + + while (1) { /* this loop will go until the comment is + * copied */ + switch (*buf_ptr) { /* this checks for various spcl cases */ + case 014: /* check for a form feed */ + CHECK_SIZE_COM(3); + if (!ps.box_com) { /* in a text comment, break the line here */ + ps.use_ff = true; + /* fix so dump_line uses a form feed */ + dump_line(); + last_bl = NULL; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + while (*++buf_ptr == ' ' || *buf_ptr == '\t') + ; + } + else { + if (++buf_ptr >= buf_end) + fill_buffer(); + *e_com++ = 014; + } + break; + + case '\n': + if (had_eof) { /* check for unexpected eof */ + printf("Unterminated comment\n"); + dump_line(); + return; + } + last_bl = NULL; + CHECK_SIZE_COM(4); + if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, + * we dont ignore the newline */ + if (s_com == e_com) + *e_com++ = ' '; + if (!ps.box_com && e_com - s_com > 3) { + dump_line(); + if (star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + } + else { + ps.last_nl = 1; + if (*(e_com - 1) == ' ' || *(e_com - 1) == '\t') + last_bl = e_com - 1; + /* + * if there was a space at the end of the last line, remember + * where it was + */ + else { /* otherwise, insert one */ + last_bl = e_com; + *e_com++ = ' '; + } + } + ++line_no; /* keep track of input line number */ + if (!ps.box_com) { + int nstar = 1; + do { /* flush any blanks and/or tabs at start of + * next line */ + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '*' && --nstar >= 0) { + if (++buf_ptr >= buf_end) + fill_buffer(); + if (*buf_ptr == '/') + goto end_of_comment; + } + } while (*buf_ptr == ' ' || *buf_ptr == '\t'); + } + else if (++buf_ptr >= buf_end) + fill_buffer(); + break; /* end of case for newline */ + + case '*': /* must check for possibility of being at end + * of comment */ + if (++buf_ptr >= buf_end) /* get to next char after * */ + fill_buffer(); + CHECK_SIZE_COM(4); + if (*buf_ptr == '/') { /* it is the end!!! */ + end_of_comment: + if (++buf_ptr >= buf_end) + fill_buffer(); + if (break_delim) { + if (e_com > s_com + 3) { + dump_line(); + } + else + s_com = e_com; + *e_com++ = ' '; + } + if (e_com[-1] != ' ' && e_com[-1] != '\t' && !ps.box_com) + *e_com++ = ' '; /* ensure blank before end */ + *e_com++ = '*', *e_com++ = '/', *e_com = '\0'; + ps.just_saw_decl = l_just_saw_decl; + return; + } + else /* handle isolated '*' */ + *e_com++ = '*'; + break; + default: /* we have a random char */ + now_col = count_spaces_until(ps.com_col, s_com, e_com); + do { + CHECK_SIZE_COM(1); + *e_com = *buf_ptr++; + if (buf_ptr >= buf_end) + fill_buffer(); + if (*e_com == ' ' || *e_com == '\t') + last_bl = e_com; /* remember we saw a blank */ + ++e_com; + now_col++; + } while (!memchr("*\n\r\b\t", *buf_ptr, 6) && + (now_col <= adj_max_col || !last_bl)); + ps.last_nl = false; + if (now_col > adj_max_col && !ps.box_com && e_com[-1] > ' ') { + /* + * the comment is too long, it must be broken up + */ + if (last_bl == NULL) { + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + break; + } + *e_com = '\0'; + e_com = last_bl; + dump_line(); + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + for (t_ptr = last_bl + 1; *t_ptr == ' ' || *t_ptr == '\t'; + t_ptr++) + ; + last_bl = NULL; + /* + * t_ptr will be somewhere between e_com (dump_line() reset) + * and l_com. So it's safe to copy byte by byte from t_ptr + * to e_com without any CHECK_SIZE_COM(). + */ + while (*t_ptr != '\0') { + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } + } + break; + } + } +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0 b/src/tools/pg_bsd_indent/tests/binary.0 new file mode 100644 index 0000000000..0c5ebf7e8f --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0 @@ -0,0 +1,9 @@ +#define b00101010 -1 +void t(void) { + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/binary.0.stdout b/src/tools/pg_bsd_indent/tests/binary.0.stdout new file mode 100644 index 0000000000..6118ac5055 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/binary.0.stdout @@ -0,0 +1,11 @@ +#define b00101010 -1 +void +t(void) +{ + unsigned a[] = {0b00101010, 0x00005678, 02, 17U}; + float x[] = {.7f, 0.7f}; + unsigned long ul[] = {0b00001111UL, 0x01010101UL, 02UL, 17UL}; + + if (0 b00101010) + return; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0 b/src/tools/pg_bsd_indent/tests/comments.0 new file mode 100644 index 0000000000..7b65c2eb55 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0 @@ -0,0 +1,52 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void t(void) { + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on the next line. + * + * *test* + */ + + /* r309219 Go through linked list, freeing from the malloced (t[-1]) address. */ + + /* r309343 */ +} + +int c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.0.stdout b/src/tools/pg_bsd_indent/tests/comments.0.stdout new file mode 100644 index 0000000000..8ca5aa518c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.0.stdout @@ -0,0 +1,60 @@ +/* $FreeBSD$ */ +typedef enum x { + aaaaaaaaaaaaaaaaaaaaaa = 1 << 0, /* test a */ + bbbbbbbbbbbbbbbbb = 1 << 1, /* test b */ + cccccccccccccc = 1 << 1, /* test c */ + dddddddddddddddddddddddddddddd = 1 << 2 /* test d */ +} x; + +/* See r303597, r303598, r309219, and r309343 */ +void +t(void) +{ + /* + * Old indent wrapped the URL near where this sentence ends. + * + * https://www.freebsd.org/cgi/man.cgi?query=indent&apropos=0&sektion=0&manpath=FreeBSD+12-current&arch=default&format=html + */ + + /* + * Old indent did not wrap to column 78 + * + * aaaaaa bbbbbb cccccc dddddd eeeeee ffffff ggggg hhhhh iiiii jjjj + * kk + */ + + /* + * Old indent unnecessarily removed the star comment continuation on + * the next line. + * + * *test* + */ + + /* + * r309219 Go through linked list, freeing from the malloced (t[-1]) + * address. + */ + + /* r309343 */ +} + +int +c(void) +{ + if (1) { /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 7; + } + + if (1) /*- a christmas tree * + *** + ***** */ + /*- another one * + *** + ***** */ + 1; +} diff --git a/src/tools/pg_bsd_indent/tests/comments.pro b/src/tools/pg_bsd_indent/tests/comments.pro new file mode 100644 index 0000000000..0959711b3d --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/comments.pro @@ -0,0 +1 @@ +-bbb \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0 b/src/tools/pg_bsd_indent/tests/cppelsecom.0 new file mode 100644 index 0000000000..79aed65115 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0 @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout new file mode 100644 index 0000000000..047fc3d951 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/cppelsecom.0.stdout @@ -0,0 +1,7 @@ +#if 1 /* if */ + +#elif defined(test) /* elif */ + +#else /* else */ + +#endif /* endif */ diff --git a/src/tools/pg_bsd_indent/tests/declarations.0 b/src/tools/pg_bsd_indent/tests/declarations.0 new file mode 100644 index 0000000000..8419494989 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0 @@ -0,0 +1,79 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct +{ + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex +{ + double x; + double y; +} Complex; + +void +t1 (char *a, int b, + void (*fn)(void)) +{} + +void t2 (char *x, int y) +{ + int a, + b, + c; + int + *d, + *e, + *f; + int (*g)(), + (*h)(), + (*i)(); + int j, + k, + l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int *int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( +struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/declarations.0.stdout b/src/tools/pg_bsd_indent/tests/declarations.0.stdout new file mode 100644 index 0000000000..ab5a447a8b --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/declarations.0.stdout @@ -0,0 +1,73 @@ +/* $FreeBSD$ */ +/* See r303570 */ + +typedef void (*voidptr) (int *); + +static const struct { + double x; + double y, z; +} n[m + 1] = +{ + { + .0, + .9, + 5 + } +}; + +typedef struct Complex { + double x; + double y; +} Complex; + +void +t1(char *a, int b, + void (*fn) (void)) +{ +} + +void +t2(char *x, int y) +{ + int a, b, c; + int + *d, *e, *f; + int (*g) (), (*h) (), (*i) (); + int j, k, l; + int m + ,n + ,o + ; + int chars[ /* push the comma beyond column 74 .... */ ], + x; +} + +const int int_minimum_size = +MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF; + +int * +int_create(void) +{ + +} + +static +_attribute_printf(1, 2) +void +print_error(const char *fmt,...) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shutingdown = 0; +struct thread *ald_thread; + +static int +do_execve( + struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0 b/src/tools/pg_bsd_indent/tests/elsecomment.0 new file mode 100644 index 0000000000..61066c22b5 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0 @@ -0,0 +1,42 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void t(void) { + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ int a; else /* b */ int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) { + int a; + } + + + else if (0) { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout new file mode 100644 index 0000000000..7de23be089 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.0.stdout @@ -0,0 +1,47 @@ +/* $FreeBSD$ */ +/* See r303484 and r309342 */ +void +t(void) +{ + /* The two if statements below excercise two different code paths. */ + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) /* a */ + int a; + else /* b */ + int b; + + if (1) + { + + } + + + + /* Old indent would remove the 3 blank lines above, awaiting "else". */ + + if (1) + { + int a; + } else if (0) + { + int b; + } + /* test */ + else + ; + + if (1) + ; + else /* Old indent would get very confused here */ + /* We also mustn't assume that there's only one comment */ + /* before the left brace. */ + { + + + } +} diff --git a/src/tools/pg_bsd_indent/tests/elsecomment.pro b/src/tools/pg_bsd_indent/tests/elsecomment.pro new file mode 100644 index 0000000000..115c4768e7 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/elsecomment.pro @@ -0,0 +1 @@ +-bl \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/enum.0 b/src/tools/pg_bsd_indent/tests/enum.0 new file mode 100644 index 0000000000..15057dc464 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0 @@ -0,0 +1,6 @@ +typedef enum +{ +PREWARM_PREFETCH, /* comment */ +PREWARM_READ, /* more comment */ +PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/enum.0.stdout b/src/tools/pg_bsd_indent/tests/enum.0.stdout new file mode 100644 index 0000000000..fd4653b854 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/enum.0.stdout @@ -0,0 +1,5 @@ +typedef enum { + PREWARM_PREFETCH, /* comment */ + PREWARM_READ, /* more comment */ + PREWARM_BUFFER /* more comment */ +} PrewarmType; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0 b/src/tools/pg_bsd_indent/tests/f_decls.0 new file mode 100644 index 0000000000..aeef03b704 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0 @@ -0,0 +1,27 @@ +char * x(void) +{ + type identifier; + type *pointer; + unused * value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) { + +} + +int +z(void) { + +} + +int x; +int *y; +int * * * * z; diff --git a/src/tools/pg_bsd_indent/tests/f_decls.0.stdout b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout new file mode 100644 index 0000000000..bc21248552 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/f_decls.0.stdout @@ -0,0 +1,30 @@ +char * +x(void) +{ + type identifier; + type *pointer; + unused *value; + (void)unused * value; + + dmax = (double)3 * 10.0; + dmin = (double)dmax * 10.0; + davg = (double)dmax * dmin; + + return NULL; +} + +int * +y(void) +{ + +} + +int +z(void) +{ + +} + +int x; +int *y; +int ****z; diff --git a/src/tools/pg_bsd_indent/tests/float.0 b/src/tools/pg_bsd_indent/tests/float.0 new file mode 100644 index 0000000000..91f017fc1c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void t(void) { + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/float.0.stdout b/src/tools/pg_bsd_indent/tests/float.0.stdout new file mode 100644 index 0000000000..0f213182ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/float.0.stdout @@ -0,0 +1,8 @@ +/* $FreeBSD$ */ +/* See r303499 */ +void +t(void) +{ + unsigned long x = 314UL; + float y = 3.14f; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0 b/src/tools/pg_bsd_indent/tests/label.0 new file mode 100644 index 0000000000..7798a4d5c2 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0 @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void t(void) { + switch (1) + { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.0.stdout b/src/tools/pg_bsd_indent/tests/label.0.stdout new file mode 100644 index 0000000000..22ec12272a --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.0.stdout @@ -0,0 +1,14 @@ +/* $FreeBSD$ */ +/* See r303489 */ +void +t(void) +{ + switch (1) { + case 1: /* test */ + case 2: /* test */ + } +CLEANUP: + ; +V: ; +U: ; +} diff --git a/src/tools/pg_bsd_indent/tests/label.pro b/src/tools/pg_bsd_indent/tests/label.pro new file mode 100644 index 0000000000..75d1fe1a12 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/label.pro @@ -0,0 +1 @@ +-nut \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/list_head.0 b/src/tools/pg_bsd_indent/tests/list_head.0 new file mode 100644 index 0000000000..35874ebc4e --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0 @@ -0,0 +1,15 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, +struct image_args *args, +struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; + + diff --git a/src/tools/pg_bsd_indent/tests/list_head.0.stdout b/src/tools/pg_bsd_indent/tests/list_head.0.stdout new file mode 100644 index 0000000000..2ebcca5730 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/list_head.0.stdout @@ -0,0 +1,13 @@ +/* $FreeBSD$ */ +/* See r309380 */ +static int +do_execve(struct thread *td, + struct image_args *args, + struct mac *mac_p) +{ + +} + +static LIST_HEAD(, alq) ald_active; +static int ald_shuttingdown = 0; +struct thread *ald_thread; diff --git a/src/tools/pg_bsd_indent/tests/nsac.0 b/src/tools/pg_bsd_indent/tests/nsac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.0.stdout b/src/tools/pg_bsd_indent/tests/nsac.0.stdout new file mode 100644 index 0000000000..78f3b28757 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double)8; +} diff --git a/src/tools/pg_bsd_indent/tests/nsac.pro b/src/tools/pg_bsd_indent/tests/nsac.pro new file mode 100644 index 0000000000..6bcbd2b1ff --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/nsac.pro @@ -0,0 +1 @@ +-nsac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0 b/src/tools/pg_bsd_indent/tests/offsetof.0 new file mode 100644 index 0000000000..078db19c29 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0 @@ -0,0 +1,5 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void t(void) { + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/offsetof.0.stdout b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout new file mode 100644 index 0000000000..199bf0fa07 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/offsetof.0.stdout @@ -0,0 +1,7 @@ +/* $FreeBSD$ */ +/* See r303718 */ +void +t(void) +{ + int n = malloc(offsetof(struct s, f) + 1); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0 b/src/tools/pg_bsd_indent/tests/parens.0 new file mode 100644 index 0000000000..366536ce82 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0 @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) + { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.0.stdout b/src/tools/pg_bsd_indent/tests/parens.0.stdout new file mode 100644 index 0000000000..2258f8d2f0 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.0.stdout @@ -0,0 +1,26 @@ +typedef void (*pgstat_page) (pgstattuple_type *, Relation, BlockNumber, + BufferAccessStrategy); + +typedef char (*get_relation_stats_hook_type) (int *root, + unsigned *rte, + char attnum, + float *vardata); + +void +similarity_dist(int m) +{ + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ), + *here)]; + + float4 res = DatumGetFloat4(FunctionCall2(similarity, + (here), + here)); + + if (es->verbose) { + char *sql = strVal(list_nth(fdw_private, + here)); + } + + rb->allocfunc(1); + rb2.allocfunc(7); +} diff --git a/src/tools/pg_bsd_indent/tests/parens.pro b/src/tools/pg_bsd_indent/tests/parens.pro new file mode 100644 index 0000000000..e860911a11 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/parens.pro @@ -0,0 +1 @@ +-ts4 -i4 -di12 -Tallocfunc diff --git a/src/tools/pg_bsd_indent/tests/sac.0 b/src/tools/pg_bsd_indent/tests/sac.0 new file mode 100644 index 0000000000..449eadf3ae --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0 @@ -0,0 +1,4 @@ +/* $FreeBSD$ */ +void t(void) { + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.0.stdout b/src/tools/pg_bsd_indent/tests/sac.0.stdout new file mode 100644 index 0000000000..1849b28337 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +void +t(void) +{ + int a = (double) 8; +} diff --git a/src/tools/pg_bsd_indent/tests/sac.pro b/src/tools/pg_bsd_indent/tests/sac.pro new file mode 100644 index 0000000000..2b21505c72 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/sac.pro @@ -0,0 +1 @@ +-sac \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/struct.0 b/src/tools/pg_bsd_indent/tests/struct.0 new file mode 100644 index 0000000000..83142bfb19 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0 @@ -0,0 +1,21 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + { D, E }, + { F, G } + }; +} + +void u(struct x a) { + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/struct.0.stdout b/src/tools/pg_bsd_indent/tests/struct.0.stdout new file mode 100644 index 0000000000..3861312865 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/struct.0.stdout @@ -0,0 +1,23 @@ +/* $FreeBSD$ */ + +int f(struct x *a); + +/* See r303485 */ +void +t(void) +{ + static const struct { + int a; + int b; + } c[] = { + {D, E}, + {F, G} + }; +} + +void +u(struct x a) +{ + int b; + struct y c = (struct y *)&a; +} diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0 b/src/tools/pg_bsd_indent/tests/surplusbad.0 new file mode 100644 index 0000000000..07d07026db --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0 @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout new file mode 100644 index 0000000000..b288970fb9 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.0.stdout @@ -0,0 +1,9 @@ +/* $FreeBSD$ */ +/* See r303599 */ +#if defined(__i386__) +int a; +#elif defined(__amd64__) +int b; +#else +#error "Port me" +#endif diff --git a/src/tools/pg_bsd_indent/tests/surplusbad.pro b/src/tools/pg_bsd_indent/tests/surplusbad.pro new file mode 100644 index 0000000000..e828c8191c --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/surplusbad.pro @@ -0,0 +1 @@ +-bad \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0 b/src/tools/pg_bsd_indent/tests/types_from_file.0 new file mode 100644 index 0000000000..6efca24fe1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0 @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c *z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout new file mode 100644 index 0000000000..8776ca6ba8 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.0.stdout @@ -0,0 +1,3 @@ +/* $FreeBSD$ */ +/* See r303735 */ +void t(a *x, b *y, c * z); diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.list b/src/tools/pg_bsd_indent/tests/types_from_file.list new file mode 100644 index 0000000000..5f733616b1 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.list @@ -0,0 +1,2 @@ +b +a \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/types_from_file.pro b/src/tools/pg_bsd_indent/tests/types_from_file.pro new file mode 100644 index 0000000000..39eb911980 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/types_from_file.pro @@ -0,0 +1 @@ +-Utypes_from_file.list \ No newline at end of file diff --git a/src/tools/pg_bsd_indent/tests/wchar.0 b/src/tools/pg_bsd_indent/tests/wchar.0 new file mode 100644 index 0000000000..9910e77857 --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0 @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; diff --git a/src/tools/pg_bsd_indent/tests/wchar.0.stdout b/src/tools/pg_bsd_indent/tests/wchar.0.stdout new file mode 100644 index 0000000000..92774abfdd --- /dev/null +++ b/src/tools/pg_bsd_indent/tests/wchar.0.stdout @@ -0,0 +1,6 @@ +/* $FreeBSD$ */ +/* See r309220 */ +#include <wchar.h> + +wchar_t *x = L"test"; +wchar_t y = L't'; -- 2.31.1 From da770680de94ba589cb29310f42f71c2373e81cf Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 14:08:57 -0500 Subject: [PATCH v4 2/5] Sync pg_bsd_indent's copyright notices with Postgres practice. To avoid confusion, make the copyright notices in these files match the 3-clause form of the BSD license, per the blanket policy update that UC Berkeley issued years ago. Discussion: https://postgr.es/m/20230123011002.fzcaa3krql3mqsfn@awork3.anarazel.de --- src/tools/pg_bsd_indent/README | 37 ++++++++++++++++++++++++++ src/tools/pg_bsd_indent/args.c | 6 +---- src/tools/pg_bsd_indent/indent.c | 6 +---- src/tools/pg_bsd_indent/indent_codes.h | 6 +---- src/tools/pg_bsd_indent/indent_globs.h | 6 +---- src/tools/pg_bsd_indent/io.c | 6 +---- src/tools/pg_bsd_indent/lexi.c | 6 +---- src/tools/pg_bsd_indent/parse.c | 6 +---- src/tools/pg_bsd_indent/pr_comment.c | 6 +---- 9 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 33d016db62..846855d318 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +The FreeBSD originals of the files in this directory bear the +"4-clause" version of the BSD license. We have removed the +"advertising" clauses, as per UC Berkeley's directive here: +ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change +which reads: + +July 22, 1999 + +To All Licensees, Distributors of Any Version of BSD: + +As you know, certain of the Berkeley Software Distribution ("BSD") source +code files require that further distributions of products containing all or +portions of the software, acknowledge within their advertising materials +that such products contain software developed by UC Berkeley and its +contributors. + +Specifically, the provision reads: + +" * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors." + +Effective immediately, licensees and distributors are no longer required to +include the acknowledgement within advertising materials. Accordingly, the +foregoing paragraph of those BSD Unix files containing it is hereby deleted +in its entirety. + +William Hoskins +Director, Office of Technology Licensing +University of California, Berkeley + +---------- + +What follows is the README file as maintained by FreeBSD indent. + +---------- $FreeBSD: head/usr.bin/indent/README 105244 2002-10-16 13:58:39Z charnier $ diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index 1c83f57049..b18eab5d39 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index d3a0ecefe9..0024993844 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_codes.h b/src/tools/pg_bsd_indent/indent_codes.h index 24c43fa420..6576bef75d 100644 --- a/src/tools/pg_bsd_indent/indent_codes.h +++ b/src/tools/pg_bsd_indent/indent_codes.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/indent_globs.h b/src/tools/pg_bsd_indent/indent_globs.h index 398784b3f4..917961bd3d 100644 --- a/src/tools/pg_bsd_indent/indent_globs.h +++ b/src/tools/pg_bsd_indent/indent_globs.h @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/io.c b/src/tools/pg_bsd_indent/io.c index 3ce8bfb70c..4149424294 100644 --- a/src/tools/pg_bsd_indent/io.c +++ b/src/tools/pg_bsd_indent/io.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/lexi.c b/src/tools/pg_bsd_indent/lexi.c index f01596a870..943bf7ce6b 100644 --- a/src/tools/pg_bsd_indent/lexi.c +++ b/src/tools/pg_bsd_indent/lexi.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/parse.c b/src/tools/pg_bsd_indent/parse.c index bf6b1697f9..e707da639c 100644 --- a/src/tools/pg_bsd_indent/parse.c +++ b/src/tools/pg_bsd_indent/parse.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/src/tools/pg_bsd_indent/pr_comment.c b/src/tools/pg_bsd_indent/pr_comment.c index b0eacac1bb..a9572b39ff 100644 --- a/src/tools/pg_bsd_indent/pr_comment.c +++ b/src/tools/pg_bsd_indent/pr_comment.c @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * -- 2.31.1 From 3d6bd52162c733bf68e702efae569a945a630e3d Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 18:38:14 -0500 Subject: [PATCH v4 3/5] Integrate pg_bsd_indent into our build/test infrastructure. Update the Makefile and build directions for in-tree build, and add Meson build infrastructure. Also convert the ad-hoc test target into a TAP test. Currently, the Make build system will not build pg_bsd_indent by default, while the Meson system will. Both will test it during "make check-world" or "ninja test". Neither will install it automatically. (We might change some of these decisions later.) Also fix a couple of portability nits noted during early testing. Also, exclude pg_bsd_indent from pgindent's purview; at least for now, we'll leave it formatted similarly to the FreeBSD original. Tom Lane and Andres Freund Discussion: https://postgr.es/m/20200812223409.6di3y2qsnvynao7a@alap3.anarazel.de --- GNUmakefile.in | 2 +- src/Makefile | 2 + src/meson.build | 2 + src/tools/pg_bsd_indent/.gitignore | 12 +--- src/tools/pg_bsd_indent/Makefile | 62 ++++++++++++------- src/tools/pg_bsd_indent/README | 37 +++++++++++ src/tools/pg_bsd_indent/README.pg_bsd_indent | 30 --------- src/tools/pg_bsd_indent/args.c | 2 +- src/tools/pg_bsd_indent/indent.c | 2 +- src/tools/pg_bsd_indent/indent.h | 2 +- src/tools/pg_bsd_indent/meson.build | 40 ++++++++++++ .../pg_bsd_indent/t/001_pg_bsd_indent.pl | 53 ++++++++++++++++ src/tools/pgindent/exclude_file_patterns | 4 ++ 13 files changed, 186 insertions(+), 64 deletions(-) delete mode 100644 src/tools/pg_bsd_indent/README.pg_bsd_indent create mode 100644 src/tools/pg_bsd_indent/meson.build create mode 100644 src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl diff --git a/GNUmakefile.in b/GNUmakefile.in index 5434467381..9c18c56233 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -68,7 +68,7 @@ check check-tests installcheck installcheck-parallel installcheck-tests: CHECKPR check check-tests installcheck installcheck-parallel installcheck-tests: submake-generated-headers $(MAKE) -C src/test/regress $@ -$(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin,check) +$(call recurse,check-world,src/test src/pl src/interfaces contrib src/bin src/tools/pg_bsd_indent,check) $(call recurse,checkprep, src/test src/pl src/interfaces contrib src/bin) $(call recurse,installcheck-world,src/test src/pl src/interfaces contrib src/bin,installcheck) diff --git a/src/Makefile b/src/Makefile index 79e274a476..94649c36c7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -66,11 +66,13 @@ clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ distclean maintainer-clean: $(MAKE) -C test $@ $(MAKE) -C tutorial NO_PGXS=1 $@ $(MAKE) -C test/isolation $@ + $(MAKE) -C tools/pg_bsd_indent $@ rm -f Makefile.port Makefile.global diff --git a/src/meson.build b/src/meson.build index 80fd2823a9..bceeca70f9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -13,6 +13,8 @@ subdir('pl') subdir('interfaces') +subdir('tools/pg_bsd_indent') + ### Generate a Makefile.global that's complete enough for PGXS to work. # diff --git a/src/tools/pg_bsd_indent/.gitignore b/src/tools/pg_bsd_indent/.gitignore index 4c5d8dc691..b27e3610d5 100644 --- a/src/tools/pg_bsd_indent/.gitignore +++ b/src/tools/pg_bsd_indent/.gitignore @@ -1,10 +1,4 @@ -# Global excludes across all subdirectories -*.o -*.obj -*.exe - -# Local excludes in root directory /pg_bsd_indent -/*.out -/*.list -/tests.diff +# Generated by test suite +/log/ +/tmp_check/ diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index ee046f36f0..ee3d494f40 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -1,35 +1,55 @@ #------------------------------------------------------------------------- # -# Makefile for pg_bsd_indent +# src/tools/pg_bsd_indent/Makefile # -# Copyright (c) 2017, PostgreSQL Global Development Group +# Copyright (c) 2017-2023, PostgreSQL Global Development Group # #------------------------------------------------------------------------- PGFILEDESC = "pg_bsd_indent - indent C code nicely" PGAPPICON = win32 -PROGRAM = pg_bsd_indent -OBJS = args.o err.o indent.o io.o lexi.o parse.o pr_comment.o $(WIN32RES) +subdir = src/tools/pg_bsd_indent +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global -# clean junk left behind by "make test" -EXTRA_CLEAN = *.out *.list tests.diff +OBJS = \ + $(WIN32RES) \ + args.o \ + err.o \ + indent.o \ + io.o \ + lexi.o \ + parse.o \ + pr_comment.o -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) +all: pg_bsd_indent -# pgxs.mk assumes too much about what "make check" means, so call it "test" +pg_bsd_indent: $(OBJS) | submake-libpgport + $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) + +install: all installdirs + $(INSTALL_PROGRAM) pg_bsd_indent$(X) '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +installdirs: + $(MKDIR_P) '$(DESTDIR)$(bindir)' + +uninstall: + rm -f '$(DESTDIR)$(bindir)/pg_bsd_indent$(X)' + +clean distclean maintainer-clean: + rm -f pg_bsd_indent$(X) $(OBJS) + rm -rf log/ tmp_check/ + +check: + $(prove_check) + +installcheck: + $(prove_installcheck) + +# Provide this alternate test name to allow testing pg_bsd_indent +# without building all of the surrounding Postgres installation. .PHONY: test -test: $(PROGRAM) - @rm -f tests.diff - @cp $(srcdir)/tests/*.list . - @for testsrc in $(srcdir)/tests/*.0; do \ - test=`basename "$$testsrc" .0`; \ - ./$(PROGRAM) $$testsrc $$test.out -P$(srcdir)/tests/$$test.pro || echo FAILED >>$$test.out; \ - diff -u $$testsrc.stdout $$test.out >>tests.diff 2>&1 || true; \ - done - @cat tests.diff - @test '!' -s tests.diff - @echo Tests complete. +test: pg_bsd_indent + $(prove_installcheck) diff --git a/src/tools/pg_bsd_indent/README b/src/tools/pg_bsd_indent/README index 846855d318..992d4fce61 100644 --- a/src/tools/pg_bsd_indent/README +++ b/src/tools/pg_bsd_indent/README @@ -1,3 +1,40 @@ +src/tools/pg_bsd_indent/README + +This is a lightly modified version of the "indent" program maintained +by the FreeBSD project. The modifications are mostly to make it portable +to non-BSD-ish platforms, though we do have one formatting switch we +couldn't convince upstream to take. + +To build it, configure the surrounding Postgres source tree, +then run "make" in this directory. +Optionally, run "make test" for some simple tests. + +You'll need to install pg_bsd_indent somewhere in your PATH before +using it. Most likely, if you're a developer, you don't want to +put it in the same place as where the surrounding Postgres build +gets installed. Therefore, do this part with something like + + make install prefix=/usr/local + +If you are using Meson to build, the standard build targets will +build pg_bsd_indent and also test it, but there is not currently +provision for installing it anywhere. Manually copy the built +executable from build/src/tools/pg_bsd_indent/pg_bsd_indent to +wherever you want to put it. + + +If you happen to be hacking upon the indent source code, the closest +approximation to the existing indentation style seems to be + + ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c + +although this has by no means been rigorously adhered to. +(What was that saw about the shoemaker's children?) +We're not planning to re-indent to Postgres style, because that +would make it difficult to compare to the FreeBSD sources. + +---------- + The FreeBSD originals of the files in this directory bear the "4-clause" version of the BSD license. We have removed the "advertising" clauses, as per UC Berkeley's directive here: diff --git a/src/tools/pg_bsd_indent/README.pg_bsd_indent b/src/tools/pg_bsd_indent/README.pg_bsd_indent deleted file mode 100644 index 85c3dcac1c..0000000000 --- a/src/tools/pg_bsd_indent/README.pg_bsd_indent +++ /dev/null @@ -1,30 +0,0 @@ -pg_bsd_indent - -This is a lightly modified version of the "indent" program maintained -by the FreeBSD project. The modifications are mostly to make it portable -to non-BSD-ish platforms, though we do have one formatting switch we -couldn't convince upstream to take. - -To build it, you will need a Postgres installation, version 9.5 or newer. -(Once built, the program doesn't depend on that installation.) - -To build, just say "make"; or if pg_config from your Postgres installation -isn't in your PATH, say - make PG_CONFIG=path/to/pg_config -Optionally, run "make test" for some simple sanity checks. - -To install, copy pg_bsd_indent to somewhere in your usual PATH. -(If you say "make install", it will try to put it in your Postgres -installation directory, which is most likely not what you want for -long-term use.) - -TODO: add build support and instructions for Windows - - -If you happen to be hacking upon the indent source code, the closest -approximation to the existing indentation style seems to be - - ./pg_bsd_indent -i4 -l79 -di12 -nfc1 -nlp -sac somefile.c - -although this has by no means been rigorously adhered to. -(What was that saw about the shoemaker's children?) diff --git a/src/tools/pg_bsd_indent/args.c b/src/tools/pg_bsd_indent/args.c index b18eab5d39..d08b086a88 100644 --- a/src/tools/pg_bsd_indent/args.c +++ b/src/tools/pg_bsd_indent/args.c @@ -176,7 +176,7 @@ void set_profile(const char *profile_name) { FILE *f; - char fname[PATH_MAX]; + char fname[MAXPGPATH]; static char prof[] = ".indent.pro"; if (profile_name == NULL) diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index 0024993844..34205f2ead 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -60,7 +60,7 @@ const char *in_name = "Standard Input"; /* will always point to name of input * file */ const char *out_name = "Standard Output"; /* will always point to name * of output file */ -char bakfile[MAXPATHLEN] = ""; +char bakfile[MAXPGPATH] = ""; int main(int argc, char **argv) diff --git a/src/tools/pg_bsd_indent/indent.h b/src/tools/pg_bsd_indent/indent.h index 1708dbc19f..d9fff8ccd6 100644 --- a/src/tools/pg_bsd_indent/indent.h +++ b/src/tools/pg_bsd_indent/indent.h @@ -28,7 +28,7 @@ __FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 303746 2016-08-04 15:27:09Z pfg $"); #endif -#define nitems(array) (sizeof (array) / sizeof (array[0])) +#define nitems(x) (sizeof((x)) / sizeof((x)[0])) void add_typename(const char *); void alloc_typenames(void); diff --git a/src/tools/pg_bsd_indent/meson.build b/src/tools/pg_bsd_indent/meson.build new file mode 100644 index 0000000000..5545c097bf --- /dev/null +++ b/src/tools/pg_bsd_indent/meson.build @@ -0,0 +1,40 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +pg_bsd_indent_sources = files( + 'args.c', + 'err.c', + 'indent.c', + 'io.c', + 'lexi.c', + 'parse.c', + 'pr_comment.c', +) + +if host_system == 'windows' + pg_bsd_indent_sources += rc_bin_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'pg_bsd_indent', + '--FILEDESC', 'pg_bsd_indent - indent C code nicely']) +endif + +pg_bsd_indent = executable('pg_bsd_indent', + pg_bsd_indent_sources, + dependencies: [frontend_code], + include_directories: include_directories('.'), + kwargs: default_bin_args + { + 'install': false, +# possibly at some point do this: +# 'install_dir': dir_pgxs / 'src/tools/pg_bsd_indent', + }, +) +bin_targets += pg_bsd_indent + +tests += { + 'name': 'pg_bsd_indent', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_pg_bsd_indent.pl', + ], + }, +} diff --git a/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl new file mode 100644 index 0000000000..b40b3fdbbf --- /dev/null +++ b/src/tools/pg_bsd_indent/t/001_pg_bsd_indent.pl @@ -0,0 +1,53 @@ +# pg_bsd_indent: some simple tests + +# The test cases come from FreeBSD upstream, but this test scaffolding is ours. +# Copyright (c) 2017-2023, PostgreSQL Global Development Group + +use strict; +use warnings; + +use Cwd qw(getcwd); +use File::Copy "cp"; +use File::Spec; + +use PostgreSQL::Test::Utils; +use Test::More; + +# We expect to be started in the source directory (even in a VPATH build); +# we want to run pg_bsd_indent in the tmp_check directory to reduce clutter. +# (Also, it's caller's responsibility that pg_bsd_indent be in the PATH.) +my $src_dir = getcwd; +chdir ${PostgreSQL::Test::Utils::tmp_check}; + +# Basic tests: pg_bsd_indent knows --version but not much else. +program_version_ok('pg_bsd_indent'); + +# Run pg_bsd_indent on pre-fab test cases. +# Any diffs in the generated files will be accumulated here. +my $diff_file = "tests.diff"; + +# Copy support files to current dir, so *.pro files don't need to know path. +while (my $file = glob("$src_dir/tests/*.list")) +{ + cp($file, ".") || die "cp $file failed: $!"; +} + +while (my $test_src = glob("$src_dir/tests/*.0")) +{ + # extract test basename + my ($volume, $directories, $test) = File::Spec->splitpath($test_src); + $test =~ s/\.0$//; + # run pg_bsd_indent + command_ok( + [ + 'pg_bsd_indent', $test_src, + "$test.out", "-P$src_dir/tests/$test.pro" + ], + "pg_bsd_indent succeeds on $test"); + # check result matches, adding any diff to $diff_file + my $result = run_log([ 'diff', '-upd', "$test_src.stdout", "$test.out" ], + '>>', $diff_file); + ok($result, "pg_bsd_indent output matches for $test"); +} + +done_testing(); diff --git a/src/tools/pgindent/exclude_file_patterns b/src/tools/pgindent/exclude_file_patterns index f5c8857e31..6405a00511 100644 --- a/src/tools/pgindent/exclude_file_patterns +++ b/src/tools/pgindent/exclude_file_patterns @@ -47,6 +47,10 @@ src/pl/plperl/ppport\.h$ src/pl/plperl/SPI\.c$ src/pl/plperl/Util\.c$ # +# pg_bsd_indent has its own, idiosyncratic indentation style. +# We'll stick to that to permit comparison with the FreeBSD upstream. +src/tools/pg_bsd_indent/.* +# # Exclude any temporary installations that may be in the tree. /tmp_check/ /tmp_install/ -- 2.31.1 From 2395910690a0d2ada0ca6df4fe8983e268811be9 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 19:28:26 -0500 Subject: [PATCH v4 4/5] Add missing test dependency. I'd supposed there was already such a dependency for 'check', but nope. Per cfbot. --- src/tools/pg_bsd_indent/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pg_bsd_indent/Makefile b/src/tools/pg_bsd_indent/Makefile index ee3d494f40..b138bb8b12 100644 --- a/src/tools/pg_bsd_indent/Makefile +++ b/src/tools/pg_bsd_indent/Makefile @@ -41,7 +41,7 @@ clean distclean maintainer-clean: rm -f pg_bsd_indent$(X) $(OBJS) rm -rf log/ tmp_check/ -check: +check: pg_bsd_indent $(prove_check) installcheck: -- 2.31.1 From ad1b9e767d5f13df6602f669fb5b3349e5f492bd Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 11 Feb 2023 20:38:25 -0500 Subject: [PATCH v4 5/5] Open output file in binary mode. This is to keep pg_bsd_indent from inserting Windows-style newlines on Windows systems. Per cfbot. Discussion: https://postgr.es/m/734490.1676165550@sss.pgh.pa.us --- src/tools/pg_bsd_indent/indent.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/pg_bsd_indent/indent.c b/src/tools/pg_bsd_indent/indent.c index 34205f2ead..2fd8771083 100644 --- a/src/tools/pg_bsd_indent/indent.c +++ b/src/tools/pg_bsd_indent/indent.c @@ -207,7 +207,7 @@ main(int argc, char **argv) * the file */ errx(1, "input and output files must be different"); } - output = fopen(out_name, "w"); + output = fopen(out_name, "wb"); if (output == NULL) /* check for create error */ err(1, "%s", out_name); continue; @@ -1232,7 +1232,7 @@ bakcopy(void) if (input == NULL) err(1, "%s", bakfile); /* now the original input file will be the output */ - output = fopen(in_name, "w"); + output = fopen(in_name, "wb"); if (output == NULL) { unlink(bakfile); err(1, "%s", in_name); -- 2.31.1
On Sun, Feb 12, 2023 at 2:44 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: > I wrote: > > Hmmm ... ci autoconf build is now happy, but the Windows run complains > > that none of the output files match. I'm betting that this is a > > Windows-newline problem, since I now see that indent.c opens both the > > input and output files in default (text) mode. I'm inclined to > > change it to open the output file in binary mode while leaving the > > input in text, which should have the effect of stripping \r if it's > > present. > > So let's see if that theory is correct at all ... (Since I happened to be tinkering on cfbot while you posted these, I noticed that cfbot took over 50 minutes to start processing the v4. The problem was upstream: the time in the second-last column of https://commitfest.postgresql.org/42/ didn't change for that whole time, even though the archives had your new email. Cf castles, sand; I should probably get a better trigger mechanism :-) I like that page because it lets me poll one single end point once per minute to learn about changes across all threads, but I am not sure what sort of technology connects the archives to the CF app, and how it can fail.)
Hello, I've discovered that the pg_bsd_indent test added here makes an ASAN-instrumented build fail on: ASAN_OPTIONS=detect_leaks=0:strict_string_checks=1 make check-world as follows: # +++ tap check in src/tools/pg_bsd_indent +++ t/001_pg_bsd_indent.pl .. 1/? # Failed test 'pg_bsd_indent succeeds on binary' # at t/001_pg_bsd_indent.pl line 41. # Failed test 'pg_bsd_indent output matches for binary' # at t/001_pg_bsd_indent.pl line 50. # Failed test 'pg_bsd_indent succeeds on comments' # at t/001_pg_bsd_indent.pl line 41. # Failed test 'pg_bsd_indent output matches for comments' # at t/001_pg_bsd_indent.pl line 50. t/001_pg_bsd_indent.pl .. 10/? ... regress_log_001_pg_bsd_indent contains: # Running: pg_bsd_indent .../src/tools/pg_bsd_indent/tests/binary.0 binary.out -P.../src/tools/pg_bsd_indent/tests/binary.pro ================================================================= ==2124067==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60600000005a at pc 0x560aa8972dae bp 0x7ffebd080460 sp 0x7ffebd07fc08 READ of size 40 at 0x60600000005a thread T0 #0 0x560aa8972dad in __interceptor_strspn.part.0 (.../src/tools/pg_bsd_indent/pg_bsd_indent+0x5edad) #1 0x560aa8a3f495 in lexi .../src/tools/pg_bsd_indent/lexi.c:258 #2 0x560aa8a3451d in main .../src/tools/pg_bsd_indent/indent.c:269 #3 0x7f6ffab1ad8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #4 0x7f6ffab1ae3f in __libc_start_main_impl ../csu/libc-start.c:392 #5 0x560aa894b7d4 in _start (.../src/tools/pg_bsd_indent/pg_bsd_indent+0x377d4) 0x60600000005a is located 0 bytes to the right of 58-byte region [0x606000000020,0x60600000005a) allocated by thread T0 here: #0 0x560aa89e4980 in __interceptor_realloc.part.0 (.../src/tools/pg_bsd_indent/pg_bsd_indent+0xd0980) #1 0x560aa8a3d24e in fill_buffer .../src/tools/pg_bsd_indent/io.c:365 SUMMARY: AddressSanitizer: heap-buffer-overflow (.../src/tools/pg_bsd_indent/pg_bsd_indent+0x5edad) in __interceptor_strspn.part.0 ... I understand that that code is almost as ancient as me and it works as intended (fill_buffer() doesn't null-terminate a buffer), but may be this is worth fixing in the Postgres source tree to keep the whole testing baseline high (if someone finds strict_string_checks useful). If so, perhaps something like the attached will do. Best regards, Alexander