Index: stable/11/etc/mtree/BSD.tests.dist =================================================================== --- stable/11/etc/mtree/BSD.tests.dist (revision 331146) +++ stable/11/etc/mtree/BSD.tests.dist (revision 331147) @@ -1,748 +1,750 @@ # $FreeBSD$ # # Please see the file src/etc/mtree/README before making changes to this file. # /set type=dir uname=root gname=wheel mode=0755 . bin cat .. chflags .. chmod .. date .. dd .. echo .. expr .. ln .. ls .. mkdir .. mv .. pax .. pkill .. pwait .. rcp .. rmdir .. sh builtins .. errors .. execution .. expansion .. parameters .. parser .. set-e .. .. sleep .. test .. .. cddl lib .. sbin .. usr.bin ctfconvert .. .. usr.sbin dtrace common aggs .. arithmetic .. arrays .. assocs .. begin .. bitfields .. buffering .. builtinvar .. cg .. clauses .. cpc .. decls .. drops .. dtraceUtil .. end .. enum .. error .. exit .. fbtprovider .. funcs .. grammar .. include .. inline .. io .. ip .. java_api .. json .. lexer .. llquantize .. mdb .. mib .. misc .. multiaggs .. offsetof .. operators .. pid .. plockstat .. pointers .. pragma .. predicates .. preprocessor .. print .. printa .. printf .. privs .. probes .. proc .. profile-n .. providers .. raise .. rates .. safety .. scalars .. sched .. scripting .. sdt .. sizeof .. speculation .. stability .. stack .. stackdepth .. stop .. strlen .. strtoll .. struct .. syscall .. sysevent .. tick-n .. trace .. tracemem .. translators .. typedef .. types .. uctf .. union .. usdt .. ustack .. vars .. version .. .. .. zfsd .. .. .. etc rc.d .. .. games .. gnu lib .. usr.bin diff .. .. .. lib atf libatf-c detail .. .. libatf-c++ detail .. .. test-programs .. .. libarchive .. libc c063 .. db .. gen execve .. posix_spawn .. .. hash data .. .. iconv .. inet .. locale .. net getaddrinfo data .. .. .. nss .. regex data .. .. resolv .. rpc .. ssp .. setjmp .. stdio .. stdlib .. string .. sys .. time .. tls dso .. .. termios .. ttyio .. .. libcam .. libcasper services cap_dns .. cap_grp .. cap_pwd .. cap_sysctl .. .. .. libcrypt .. libdevdctl .. libkvm .. libmp .. libnv .. libpam .. libproc .. librt .. libsbuf .. libthr dlopen .. .. libutil .. libxo .. msun .. .. libexec atf atf-check .. atf-sh .. .. rtld-elf .. .. sbin dhclient .. devd .. growfs .. ifconfig .. mdconfig .. .. secure lib .. libexec .. usr.bin .. usr.sbin .. .. share examples tests atf .. plain .. tap .. .. .. zoneinfo .. .. sys acl .. aio .. fifo .. file .. fs tmpfs .. .. geom class concat .. eli .. gate .. gpt .. mirror .. nop .. part .. raid3 .. shsec .. stripe .. uzip etalon .. .. .. .. kern acct .. execve .. pipe .. .. kqueue libkqueue .. .. mac bsdextended .. portacl .. .. mqueue .. netinet .. opencrypto .. pjdfstest chflags .. chmod .. chown .. ftruncate .. granular .. link .. mkdir .. mkfifo .. mknod .. open .. rename .. rmdir .. symlink .. truncate .. unlink .. .. posixshm .. sys .. vfs .. vm .. .. usr.bin apply .. basename .. bmake archives fmt_44bsd .. fmt_44bsd_mod .. fmt_oldbsd .. .. basic t0 .. t1 .. t2 .. t3 .. .. execution ellipsis .. empty .. joberr .. plus .. .. shell builtin .. meta .. path .. path_select .. replace .. select .. .. suffixes basic .. src_wild1 .. src_wild2 .. .. syntax directive-t0 .. enl .. funny-targets .. semi .. .. sysmk t0 2 1 .. .. mk .. .. t1 2 1 .. .. mk .. .. t2 2 1 .. .. mk .. .. .. variables modifier_M .. modifier_t .. opt_V .. t0 .. .. .. bsdcat .. calendar .. cmp .. compress .. cpio .. col .. comm .. cut .. dirname .. du .. file2c .. fold .. getconf .. grep .. gzip .. head .. hexdump .. ident .. + indent + .. join .. jot .. lastcomm .. limits .. m4 .. mkimg .. ncal .. opensm .. pr .. printf .. procstat .. rs .. sdiff .. sed regress.multitest.out .. .. soelim .. stat .. tail .. tar .. timeout .. tr .. truncate .. units .. uudecode .. uuencode .. uniq .. xargs .. xinstall .. xo .. yacc yacc .. .. .. usr.sbin chown .. etcupdate .. extattr .. fstyp .. makefs .. newsyslog .. nmtree .. pw .. rpcbind .. sa .. .. .. # vim: set expandtab ts=4 sw=4: Index: stable/11/usr.bin/indent/Makefile =================================================================== --- stable/11/usr.bin/indent/Makefile (revision 331146) +++ stable/11/usr.bin/indent/Makefile (revision 331147) @@ -1,9 +1,15 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= indent SRCS= indent.c io.c lexi.c parse.c pr_comment.c args.c NO_WMISSING_VARIABLE_DECLARATIONS= + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif .include Index: stable/11/usr.bin/indent/args.c =================================================================== --- stable/11/usr.bin/indent/args.c (revision 331146) +++ stable/11/usr.bin/indent/args.c (revision 331147) @@ -1,329 +1,328 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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 __FBSDID("$FreeBSD$"); /* * Argument scanning and profile reading code. Default parameters are set * here as well. */ #include #include #include #include #include #include #include "indent_globs.h" #include "indent.h" /* profile types */ #define PRO_SPECIAL 1 /* special case */ #define PRO_BOOL 2 /* boolean */ #define PRO_INT 3 /* integer */ #define PRO_FONT 4 /* troff font */ /* 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 *); const char *option_source = "?"; /* * 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}, + {"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}, {"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}, {"fbc", PRO_FONT, 0, 0, (int *) &blkcomf}, {"fbs", PRO_BOOL, true, ON, &function_brace_split}, {"fbx", PRO_FONT, 0, 0, (int *) &boxcomf}, {"fb", PRO_FONT, 0, 0, (int *) &bodyf}, {"fc1", PRO_BOOL, true, ON, &format_col1_comments}, {"fcb", PRO_BOOL, true, ON, &format_block_comments}, {"fc", PRO_FONT, 0, 0, (int *) &scomf}, {"fk", PRO_FONT, 0, 0, (int *) &keywordf}, {"fs", PRO_FONT, 0, 0, (int *) &stringf}, {"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}, {"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}, {"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}, {"nps", PRO_BOOL, false, OFF, &pointer_as_binop}, {"nsc", PRO_BOOL, true, OFF, &star_comment_cont}, {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines}, {"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}, {"ps", PRO_BOOL, false, ON, &pointer_as_binop}, {"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}, {"troff", PRO_BOOL, false, ON, &troff}, {"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(void) { FILE *f; char fname[PATH_MAX]; static char prof[] = ".indent.pro"; snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof); 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(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; } } -const char *param_start; - -static int +static const char * eqin(const char *s1, const char *s2) { while (*s1) { if (*s1++ != *s2++) - return (false); + return (NULL); } - param_start = s2; - return (true); + 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_type != PRO_FONT) *p->p_obj = p->p_default; } void set_option(char *arg) { - struct pro *p; + struct pro *p; + const char *param_start; arg++; /* ignore leading "-" */ for (p = pro; p->p_name; p++) - if (*p->p_name == *arg && eqin(p->p_name, arg)) + 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 == 0) + if (input == NULL) input = stdin; - if (output == 0) + if (output == NULL) output = stdout; break; case KEY: if (*param_start == 0) goto need_param; { char *str = strdup(param_start); if (str == NULL) err(1, NULL); addkey(str, 4); } break; 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(*param_start)) { need_param: errx(1, "%s: ``%s'' requires a parameter", option_source, arg - 1); } *p->p_obj = atoi(param_start); break; case PRO_FONT: parsefont((struct fstate *) p->p_obj, param_start); break; default: errx(1, "set_option: internal error: p_type %d", p->p_type); } } Index: stable/11/usr.bin/indent/indent.c =================================================================== --- stable/11/usr.bin/indent/indent.c (revision 331146) +++ stable/11/usr.bin/indent/indent.c (revision 331147) @@ -1,1252 +1,1289 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1985 Sun Microsystems, Inc.\n\ @(#) Copyright (c) 1976 Board of Trustees of the University of Illinois.\n\ @(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)indent.c 5.17 (Berkeley) 6/7/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); +#include #include #include +#include #include #include #include #include #include #include #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 */ const char *simple_backup_suffix = ".BAK"; /* Suffix to use for backup * files */ char bakfile[MAXPATHLEN] = ""; int main(int argc, char **argv) { + cap_rights_t rights; int dec_ind; /* current indentation for declarations */ int di_stack[20]; /* a stack of structure indentation levels */ int flushed_nl; /* used when buffering up comments to remember * that a newline was passed over */ 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 ?: * 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 *envval = NULL; /*-----------------------------------------------*\ | 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); 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 = 0; - bp_save = 0; - be_save = 0; + sc_end = NULL; + bp_save = NULL; + be_save = NULL; - output = 0; + output = NULL; tabs_to_var = 0; envval = getenv("SIMPLE_BACKUP_SUFFIX"); if (envval) simple_backup_suffix = envval; /*--------------------------------------------------*\ | COMMAND LINE SCAN | \*--------------------------------------------------*/ #ifdef undef max_col = 78; /* -l78 */ lineup_to_parens = 1; /* -lp */ 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; set_defaults(); if (i >= argc) set_profile(); 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 (troff || input == stdin) output = stdout; else { out_name = in_name; bakcopy(); } } + + /* Restrict input/output descriptors and enter Capsicum sandbox. */ + cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE); + if (cap_rights_limit(fileno(output), &rights) < 0 && errno != ENOSYS) + err(EXIT_FAILURE, "unable to limit rights for %s", out_name); + cap_rights_init(&rights, CAP_FSTAT, CAP_READ); + if (cap_rights_limit(fileno(input), &rights) < 0 && errno != ENOSYS) + err(EXIT_FAILURE, "unable to limit rights for %s", in_name); + if (cap_enter() < 0 && errno != ENOSYS) + err(EXIT_FAILURE, "unable to enter capability mode"); + if (ps.com_ind <= 1) ps.com_ind = 2; /* dont put normal comments before column 2 */ if (troff) { if (bodyf.font[0] == 0) parsefont(&bodyf, "R"); if (scomf.font[0] == 0) parsefont(&scomf, "I"); if (blkcomf.font[0] == 0) blkcomf = scomf, blkcomf.size += 2; if (boxcomf.font[0] == 0) boxcomf = blkcomf; if (stringf.font[0] == 0) parsefont(&stringf, "L"); if (keywordf.font[0] == 0) parsefont(&keywordf, "B"); writefdef(&bodyf, 'B'); writefdef(&scomf, 'C'); writefdef(&blkcomf, 'L'); writefdef(&boxcomf, 'X'); writefdef(&stringf, 'S'); writefdef(&keywordf, 'K'); } 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 = ((col - 1) & ~7) + 9; else break; p++; } if (col > ps.ind_size) ps.ind_level = ps.i_l_follow = col / ps.ind_size; } if (troff) { const char *p = in_name, *beg = in_name; while (*p) if (*p++ == '/') beg = p; fprintf(output, ".Fn \"%s\"\n", beg); } /* * START OF MAIN LOOP */ while (1) { /* this is the main loop. it will go until we * reach eof */ int is_procname; type_code = lexi(); /* lexi reads one token. The actual * characters read are stored in "token". lexi * returns a code indicating the type of token */ is_procname = ps.procname[0]; /* * The following code moves everything 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. */ flushed_nl = false; while (ps.search_brace) { /* if we scanned an if(), while(), * etc., we might need to copy stuff * into a buffer we must loop, copying * stuff into save_com, until we find * the start of the stmt which follows * the if, or whatever */ switch (type_code) { case newline: ++line_no; + if (sc_end != NULL) { /* dump comment, if any */ + *sc_end++ = '\n'; /* newlines are needed in this case */ + goto sw_buffer; + } flushed_nl = true; case form_feed: break; /* form feeds and newlines found here will be * ignored */ case lbrace: /* this is a brace that starts the compound * stmt */ - if (sc_end == 0) { /* ignore buffering if a comment wasn't + if (sc_end == NULL) { /* ignore buffering if a comment wasn't * stored up */ ps.search_brace = false; goto check_type; } if (btype_2) { save_com[0] = '{'; /* we either want to put the brace * right after the if */ goto sw_buffer; /* go to common code to get out of * this loop */ } case comment: /* we have a comment, so we must copy it into * the buffer */ - if (!flushed_nl || sc_end != 0) { - if (sc_end == 0) { /* if this is the first comment, we - * must set up the buffer */ + if (!flushed_nl || sc_end != NULL) { + if (sc_end == NULL) { /* if this is the first comment, we + * must set up the buffer */ save_com[0] = save_com[1] = ' '; sc_end = &(save_com[2]); } else { *sc_end++ = '\n'; /* add newline between * comments */ *sc_end++ = ' '; --line_no; } *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; } default: /* it is the start of a normal statement */ if (flushed_nl) /* if we flushed a newline, make sure it is * put back */ force_nl = true; if ((type_code == sp_paren && *token == 'i' && last_else && ps.else_if) || (type_code == sp_nparen && *token == 'e' && e_code != s_code && e_code[-1] == '}')) force_nl = false; - if (sc_end == 0) { /* ignore buffering if comment wasn't + if (sc_end == NULL) { /* ignore buffering if comment wasn't * saved up */ ps.search_brace = false; goto check_type; } 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 nl is * read from the buffer */ *sc_end++ = '\n'; *sc_end++ = ' '; if (verbose && !flushed_nl) /* print error msg if the line * was not already broken */ diag2(0, "Line broken"); flushed_nl = false; } for (t_ptr = token; *t_ptr; ++t_ptr) *sc_end++ = *t_ptr; /* copy token into temp buffer */ ps.procname[0] = 0; 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 = 0; + sc_end = NULL; break; } /* end of switch */ if (type_code != 0) /* we must make this check, just in case there * was an unexpected EOF */ type_code = lexi(); /* read another token */ /* if (ps.search_brace) ps.procname[0] = 0; */ if ((is_procname = ps.procname[0]) && flushed_nl && !procnames_start_line && ps.in_decl && type_code == ident) flushed_nl = 0; } /* 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 && !flushed_nl) diag2(0, "Line broken"); flushed_nl = false; 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 */ *e_code++ = ' '; for (t_ptr = s_com; *t_ptr; ++t_ptr) { CHECK_SIZE_CODE; *e_code++ = *t_ptr; } *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; 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 '[' */ - ++ps.p_l_follow; /* count parens to make Healy happy */ + /* 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 (ps.want_blank && *token != '[' && - (ps.last_token != ident || proc_calls_space - || (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon)))) + (ps.last_token != ident || proc_calls_space || + /* 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++ = ' '; - if (ps.in_decl && !ps.block_init) - if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) { - ps.dumped_decl_indent = 1; + ps.want_blank = false; + if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent && + !is_procname) { + /* function pointer declarations */ + if (troff) { sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); e_code += strlen(e_code); } else { - while ((e_code - s_code) < dec_ind) { - CHECK_SIZE_CODE; - *e_code++ = ' '; - } - *e_code++ = token[0]; + indent_declaration(dec_ind, tabs_to_var); } - else + ps.dumped_decl_indent = true; + } + if (!troff) *e_code++ = token[0]; ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code; 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; - ps.want_blank = false; 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 */ } - if (ps.sizeof_keyword) - ps.sizeof_mask |= 1 << ps.p_l_follow; + /* parenthesized type following sizeof or offsetof is not a cast */ + if (ps.keyword == 1 || ps.keyword == 2) + ps.not_cast_mask |= 1 << ps.p_l_follow; break; case rparen: /* got a ')' or ']' */ rparen_count--; - if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) { + 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 = false; } else ps.want_blank = true; - ps.sizeof_mask &= (1 << ps.p_l_follow) - 1; + 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.want_blank) - *e_code++ = ' '; - - if (troff && !ps.dumped_decl_indent && ps.in_decl && !is_procname) { - sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token); - ps.dumped_decl_indent = 1; - e_code += strlen(e_code); + if (!ps.dumped_decl_indent && ps.in_decl && !is_procname && + !ps.block_init) { + /* pointer declarations */ + if (troff) { + if (ps.want_blank) + *e_code++ = ' '; + sprintf(e_code, "\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, + token); + e_code += strlen(e_code); + } + else { + /* 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 { + else if (ps.want_blank) + *e_code++ = ' '; + { const char *res = token; - if (ps.in_decl && !ps.block_init) { /* if this is a unary op - * in a declaration, we - * should indent this - * token */ - for (i = 0; token[i]; ++i); /* find length of token */ - while ((e_code - s_code) < (dec_ind - i)) { - CHECK_SIZE_CODE; - *e_code++ = ' '; /* pad it */ - } - } if (troff && token[0] == '-' && token[1] == '>') res = "\\(->"; for (t_ptr = res; *t_ptr; ++t_ptr) { CHECK_SIZE_CODE; *e_code++ = *t_ptr; } } ps.want_blank = false; break; case binary_op: /* any binary operation */ if (ps.want_blank) *e_code++ = ' '; { const char *res = token; if (troff) switch (token[0]) { case '<': if (token[1] == '=') res = "\\(<="; break; case '>': if (token[1] == '=') res = "\\(>="; break; case '!': if (token[1] == '=') res = "\\(!="; break; case '|': if (token[1] == '|') res = "\\(br\\(br"; else if (token[1] == 0) res = "\\(br"; break; } for (t_ptr = res; *t_ptr; ++t_ptr) { CHECK_SIZE_CODE; *e_code++ = *t_ptr; /* move the operator */ } } 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 * ?: 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 ?: 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 */ for (t_ptr = s_code; *t_ptr; ++t_ptr) *e_lab++ = *t_ptr; /* turn everything so far into a label */ e_code = s_code; *e_lab++ = ':'; *e_lab++ = ' '; *e_lab = '\0'; 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 ';' */ - ps.in_or_st = false;/* we are not in an initialization or - * structure declaration */ + 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 && rparen_count == 0) ps.in_parameter_declaration = 0; ps.cast_mask = 0; - ps.sizeof_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) - while ((e_code - s_code) < (dec_ind - 1)) { - CHECK_SIZE_CODE; - *e_code++ = ' '; - } + if (ps.in_decl && s_code == e_code && !ps.block_init && + !ps.dumped_decl_indent) { + /* 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; /* ? 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; } 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 decl: /* we have a declaration type (int, register, * etc.) */ parse(decl); /* let parser worry about indentation */ if (ps.last_token == rparen && ps.tos <= 1) { ps.in_parameter_declaration = 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 ident: /* got an identifier or constant */ if (ps.in_decl) { /* if we are in a declaration, we must indent * identifier */ if (is_procname == 0 || !procnames_start_line) { - if (!ps.block_init) { - if (troff && !ps.dumped_decl_indent) { + if (!ps.block_init && !ps.dumped_decl_indent) { + if (troff) { if (ps.want_blank) *e_code++ = ' '; - ps.want_blank = false; sprintf(e_code, "\n.De %dp+\200p\n", dec_ind * 7); - ps.dumped_decl_indent = 1; e_code += strlen(e_code); - } else { - int cur_dec_ind; - int pos, startpos; - - /* - * in order to get the tab math right for - * indentations that are not multiples of 8 we - * need to modify both startpos and dec_ind - * (cur_dec_ind) here by eight minus the - * remainder of the current starting column - * divided by eight. This seems to be a - * properly working fix - */ - startpos = e_code - s_code; - cur_dec_ind = dec_ind; - pos = startpos; - if ((ps.ind_level * ps.ind_size) % 8 != 0) { - pos += (ps.ind_level * ps.ind_size) % 8; - cur_dec_ind += (ps.ind_level * ps.ind_size) % 8; - } - - if (tabs_to_var) { - while ((pos & ~7) + 8 <= cur_dec_ind) { - CHECK_SIZE_CODE; - *e_code++ = '\t'; - pos = (pos & ~7) + 8; - } - } - while (pos < cur_dec_ind) { - CHECK_SIZE_CODE; - *e_code++ = ' '; - pos++; - } - if (ps.want_blank && e_code - s_code == startpos) - *e_code++ = ' '; - ps.want_blank = false; - } + } else + indent_declaration(dec_ind, tabs_to_var); + ps.dumped_decl_indent = true; + ps.want_blank = false; } } else { if (ps.want_blank) *e_code++ = ' '; ps.want_blank = false; - if (dec_ind && s_code != e_code) + if (dec_ind && s_code != e_code) { + *e_code = '\0'; dump_line(); + } dec_ind = 0; } } 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: if (ps.want_blank) *e_code++ = ' '; - if (troff && ps.its_a_keyword) { + if (troff && ps.keyword) { e_code = chfont(&bodyf, &keywordf, e_code); for (t_ptr = token; *t_ptr; ++t_ptr) { CHECK_SIZE_CODE; *e_code++ = keywordf.allcaps && islower(*t_ptr) ? toupper(*t_ptr) : *t_ptr; } e_code = chfont(&keywordf, &bodyf, e_code); } else for (t_ptr = token; *t_ptr; ++t_ptr) { CHECK_SIZE_CODE; *e_code++ = *t_ptr; } ps.want_blank = true; break; case strpfx: if (ps.want_blank) *e_code++ = ' '; for (t_ptr = token; *t_ptr; ++t_ptr) { CHECK_SIZE_CODE; *e_code++ = *t_ptr; } 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 && is_procname == 0 && !ps.block_init) - while ((e_code - s_code) < (dec_ind - 1)) { - CHECK_SIZE_CODE; - *e_code++ = ' '; - } - + if (ps.in_decl && is_procname == 0 && !ps.block_init && + !ps.dumped_decl_indent) { + /* 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 || compute_code_target() + (e_code - s_code) > max_col - 8)) force_nl = true; } break; case preesc: /* got the character '#' */ if ((s_com != e_com) || (s_lab != e_lab) || (s_code != e_code)) dump_line(); *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; *e_lab = *buf_ptr++; if (buf_ptr >= buf_end) fill_buffer(); switch (*e_lab++) { case BACKSLASH: if (troff) *e_lab++ = 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 == 0) { /* comment on - * preprocessor line */ - if (sc_end == 0) /* if this is the first comment, we + 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 */ sc_end = &(save_com[0]); else { *sc_end++ = '\n'; /* add newline between * comments */ *sc_end++ = ' '; --line_no; } bcopy(s_lab + com_start, sc_end, com_end - com_start); sc_end += com_end - com_start; if (sc_end >= &save_com[sc_size]) abort(); 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 = 0; + sc_end = NULL; } *e_lab = '\0'; /* null terminate line */ ps.pcase = false; } - if (strncmp(s_lab, "#if", 3) == 0) { - if (blanklines_around_conditional_compilation) { - int c; - prefix_blankline_requested++; - while ((c = getc(input)) == '\n'); - ungetc(c, input); - } + 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, "#else", 5) == 0) + else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */ if (ifdef_level <= 0) - diag2(1, "Unmatched #else"); + 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 { + else ifdef_level--; - -#ifdef undef - /* - * This match needs to be more intelligent before the - * message is useful - */ - if (match_state[ifdef_level].tos >= 0 - && bcmp(&ps, &match_state[ifdef_level], sizeof ps)) - diag2(0, "Syntactically inconsistent #ifdef alternatives"); -#endif + } else { + struct directives { + int size; + const char *string; } - if (blanklines_around_conditional_compilation) { - postfix_blankline_requested++; - n_real_blanklines = 0; + 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 */ if (flushed_nl) { /* we should force a broken line here */ - flushed_nl = false; dump_line(); ps.want_blank = false; /* dont insert blank at line start */ force_nl = false; } 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%s", p, simple_backup_suffix); /* 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) + 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 8 + */ + if ((ps.ind_level * ps.ind_size) % 8 != 0) { + pos += (ps.ind_level * ps.ind_size) % 8; + cur_dec_ind += (ps.ind_level * ps.ind_size) % 8; + } + if (tabs_to_var) + while ((pos & ~7) + 8 <= cur_dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = '\t'; + pos = (pos & ~7) + 8; + } + while (pos < cur_dec_ind) { + CHECK_SIZE_CODE; + *e_code++ = ' '; + pos++; + } + if (e_code == startpos && ps.want_blank) { + *e_code++ = ' '; + ps.want_blank = false; } } Index: stable/11/usr.bin/indent/indent.h =================================================================== --- stable/11/usr.bin/indent/indent.h (revision 331146) +++ stable/11/usr.bin/indent/indent.h (revision 331147) @@ -1,49 +1,50 @@ -/* +/*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * 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$"); #endif void addkey(char *, int); int compute_code_target(void); int compute_label_target(void); int count_spaces(int, char *); +int count_spaces_until(int, char *, char *); int lexi(void); void diag2(int, const char *); void diag3(int, const char *, int); void diag4(int, const char *, int, int); void dump_line(void); void fill_buffer(void); void parse(int); void parsefont(struct fstate *, const char *); void pr_comment(void); void set_defaults(void); void set_option(char *); void set_profile(void); void writefdef(struct fstate *f, int); Index: stable/11/usr.bin/indent/indent_codes.h =================================================================== --- stable/11/usr.bin/indent/indent_codes.h (revision 331146) +++ stable/11/usr.bin/indent/indent_codes.h (revision 331147) @@ -1,73 +1,73 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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$ */ #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 Index: stable/11/usr.bin/indent/indent_globs.h =================================================================== --- stable/11/usr.bin/indent/indent_globs.h (revision 331146) +++ stable/11/usr.bin/indent/indent_globs.h (revision 331147) @@ -1,331 +1,336 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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$ */ #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 */ #define tabsize 8 /* the size of a tab */ #define tabmask 0177770 /* mask used when figuring length of lines * with tabs */ #define false 0 #define true 1 FILE *input; /* the fid for the input file */ FILE *output; /* the output file */ #define CHECK_SIZE_CODE \ if (e_code >= l_code) { \ int nsize = l_code-s_code+400; \ + int code_len = e_code-s_code; \ codebuf = (char *) realloc(codebuf, nsize); \ if (codebuf == NULL) \ err(1, NULL); \ - e_code = codebuf + (e_code-s_code) + 1; \ + e_code = codebuf + code_len + 1; \ l_code = codebuf + nsize - 5; \ s_code = codebuf + 1; \ } #define CHECK_SIZE_COM \ if (e_com >= l_com) { \ int nsize = l_com-s_com+400; \ + int com_len = e_com - s_com; \ + int blank_pos = last_bl - s_com; \ combuf = (char *) realloc(combuf, nsize); \ if (combuf == NULL) \ err(1, NULL); \ - e_com = combuf + (e_com-s_com) + 1; \ + e_com = combuf + com_len + 1; \ + last_bl = combuf + blank_pos + 1; \ l_com = combuf + nsize - 5; \ s_com = combuf + 1; \ } #define CHECK_SIZE_LAB \ if (e_lab >= l_lab) { \ int nsize = l_lab-s_lab+400; \ + int label_len = e_lab - s_lab; \ labbuf = (char *) realloc(labbuf, nsize); \ if (labbuf == NULL) \ err(1, NULL); \ - e_lab = labbuf + (e_lab-s_lab) + 1; \ + e_lab = labbuf + label_len + 1; \ l_lab = labbuf + nsize - 5; \ s_lab = labbuf + 1; \ } #define CHECK_SIZE_TOKEN \ if (e_token >= l_token) { \ int nsize = l_token-s_token+400; \ + int token_len = e_token - s_token; \ tokenbuf = (char *) realloc(tokenbuf, nsize); \ if (tokenbuf == NULL) \ err(1, NULL); \ - e_token = tokenbuf + (e_token-s_token) + 1; \ + e_token = tokenbuf + token_len + 1; \ l_token = tokenbuf + nsize - 5; \ s_token = tokenbuf + 1; \ } char *labbuf; /* buffer for label */ char *s_lab; /* start ... */ char *e_lab; /* .. and end of stored label */ char *l_lab; /* limit of label buffer */ char *codebuf; /* buffer for code section */ char *s_code; /* start ... */ char *e_code; /* .. and end of stored code */ char *l_code; /* limit of code section */ char *combuf; /* buffer for comments */ char *s_com; /* start ... */ char *e_com; /* ... and end of stored comments */ char *l_com; /* limit of comment buffer */ #define token s_token char *tokenbuf; /* the last token scanned */ char *s_token; char *e_token; char *l_token; char *in_buffer; /* input buffer */ char *in_buffer_limit; /* the end of the input buffer */ char *buf_ptr; /* ptr to next character to be taken from * in_buffer */ char *buf_end; /* ptr to first after last char in in_buffer */ char save_com[sc_size]; /* input text is saved here when looking for * the brace after an if, while, etc */ char *sc_end; /* pointer into save_com buffer */ char *bp_save; /* saved value of buf_ptr when taking input * from save_com */ char *be_save; /* similarly saved value of buf_end */ int found_err; int pointer_as_binop; int blanklines_after_declarations; int blanklines_before_blockcomments; int blanklines_after_procs; int blanklines_around_conditional_compilation; int swallow_optional_blanklines; int n_real_blanklines; int prefix_blankline_requested; int postfix_blankline_requested; int break_comma; /* when true and not in parens, break after a * comma */ int btype_2; /* when true, brace should be on same line as * if, while, etc */ float case_ind; /* indentation level to be used for a "case * n:" */ int code_lines; /* count of lines with code */ int had_eof; /* set to true when input is exhausted */ int line_no; /* the current line number. */ int max_col; /* the maximum allowable line length */ int verbose; /* when true, non-essential error messages are * printed */ int cuddle_else; /* true if else should cuddle up to '}' */ int star_comment_cont; /* true iff comment continuation lines should * have stars at the beginning of each line. */ int comment_delimiter_on_blankline; int troff; /* true iff were generating troff input */ 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) */ int proc_calls_space; /* If true, procedure calls look like: * foo(bar) rather than foo (bar) */ int format_block_comments; /* true if comments beginning with * `/ * \n' are to be reformatted */ int format_col1_comments; /* If comments which start in column 1 * are to be magically reformatted * (just like comments that begin in * later columns) */ int inhibit_formatting; /* true if INDENT OFF is in effect */ int suppress_blanklines;/* set iff following blanklines should be * suppressed */ int continuation_indent;/* set to the indentation between the edge of * code and continuation lines */ int lineup_to_parens; /* if true, continued code within parens will * be lined up to the open paren */ int Bill_Shannon; /* true iff a blank should always be inserted * after sizeof */ 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 */ int block_comment_max_col; 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 */ int function_brace_split; /* split function declaration and * brace onto separate lines */ int use_tabs; /* set true to use tabs for spacing, * false uses all spaces */ int auto_typedefs; /* set true to recognize identifiers * ending in "_t" like typedefs */ /* -troff font state information */ struct fstate { char font[4]; char size; int allcaps:1; } __aligned(sizeof(int)); char *chfont(struct fstate *, struct fstate *, char *); struct fstate keywordf, /* keyword font */ stringf, /* string font */ boxcomf, /* Box comment font */ blkcomf, /* Block comment font */ scomf, /* Same line comment font */ bodyf; /* major body font */ -#define STACKSIZE 150 +#define STACKSIZE 256 struct parser_state { int last_token; struct fstate cfont; /* Current font */ int p_stack[STACKSIZE]; /* this is the parsers stack */ int il[STACKSIZE]; /* this stack stores indentation levels */ float cstk[STACKSIZE];/* 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, n_comment_delta; - int cast_mask; /* indicates which close parens close off - * casts */ - int sizeof_mask; /* indicates which close parens close off - * sizeof''s */ + 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 its_a_keyword; - int sizeof_keyword; + 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; } ps; int ifdef_level; int rparen_count; struct parser_state state_stack[5]; struct parser_state match_state[5]; Index: stable/11/usr.bin/indent/io.c =================================================================== --- stable/11/usr.bin/indent/io.c (revision 331146) +++ stable/11/usr.bin/indent/io.c (revision 331147) @@ -1,669 +1,667 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "indent_globs.h" #include "indent.h" int comment_open; static int paren_target; 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]) { if (troff) { if (comment_open) { comment_open = 0; fprintf(output, ".*/\n"); } fprintf(output, ".Pr \"%s\"\n", ps.procname); } 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) { if (troff) { int all_here = 0; char *p; if (e_com[-1] == '/' && e_com[-2] == '*') e_com -= 2, all_here++; while (e_com > s_com && e_com[-1] == ' ') e_com--; *e_com = 0; p = s_com; while (*p == ' ') p++; if (p[0] == '/' && p[1] == '*') p += 2, all_here++; else if (p[0] == '*') p += p[1] == '/' ? 2 : 1; while (*p == ' ') p++; if (*p == 0) goto inhibit_newline; if (comment_open < 2 && ps.box_com) { comment_open = 0; fprintf(output, ".*/\n"); } if (comment_open == 0) { if ('a' <= *p && *p <= 'z') *p = *p + 'A' - 'a'; if (e_com - p < 50 && all_here == 2) { char *follow = p; fprintf(output, "\n.nr C! \\w\1"); while (follow < e_com) { switch (*follow) { case '\n': putc(' ', output); case 1: break; case '\\': putc('\\', output); + /* add a backslash to escape the '\' */ default: putc(*follow, output); } follow++; } putc(1, output); } fprintf(output, "\n./* %dp %d %dp\n", ps.com_col * 7, (s_code != e_code || s_lab != e_lab) - ps.box_com, target_col * 7); } comment_open = 1 + ps.box_com; while (*p) { if (*p == BACKSLASH) putc(BACKSLASH, output); putc(*p++, output); } } else { /* print comment, if any */ int target = ps.com_col; char *com_st = s_com; target += ps.comment_delta; - while (*com_st == '\t') - com_st++, target += 8; /* ? */ + while (*com_st == '\t') /* consider original indentation in + * case this is a box comment */ + com_st++, target += 8; while (target <= 0) if (*com_st == ' ') target++, com_st++; else if (*com_st == '\t') target = ((target - 1) & ~7) + 9, 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(e_com[-1])) e_com--; - cur_col = pad_output(cur_col, target); - if (!ps.box_com) { - if (star_comment_cont && (com_st[1] != '*' || e_com <= com_st + 1)) { - if (com_st[1] == ' ' && com_st[0] == ' ' && e_com > com_st + 1) - com_st[1] = '*'; - else - fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output); - } - } + (void)pad_output(cur_col, target); fwrite(com_st, e_com - com_st, 1, output); ps.comment_delta = ps.n_comment_delta; - cur_col = count_spaces(cur_col, com_st); ++ps.com_lines; /* count lines with comments */ } } if (ps.use_ff) putc('\014', output); else putc('\n', output); inhibit_newline: ++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) = '\0'; + *(e_com = s_com = combuf + 1) = '\0'; ps.ind_level = ps.i_l_follow; ps.paren_level = ps.p_l_follow; - paren_target = -ps.paren_indents[ps.paren_level - 1]; + 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 { 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; } /* * Copyright (C) 1976 by the Board of Trustees of the University of Illinois * * All rights reserved * * * NAME: fill_buffer * * FUNCTION: Reads one block of input into input_buffer * * 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 != 0) { /* there is a partly filled input buffer left */ - buf_ptr = bp_save; /* dont read anything, just switch buffers */ + 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 = 0; + bp_save = be_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 ((i = getc(f)) == EOF) { *p++ = ' '; *p++ = '\n'; had_eof = true; break; } *p++ = i; if (i == '\n') break; } buf_ptr = in_buffer; buf_end = p; - if (p[-2] == '/' && p[-3] == '*') { + 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 * nteger 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 */ int tcur; if (troff) fprintf(output, "\\h'|%dp'", (target - 1) * 7); else { if (current >= target) return (current); /* line is already long enough */ curr = current; if (use_tabs) { while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) { putc('\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(int current, char *buffer) +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 */ - int cur; /* current character counter */ - cur = current; - - for (buf = buffer; *buf != '\0'; ++buf) { + for (buf = buffer; *buf != '\0' && buf != end; ++buf) { switch (*buf) { case '\n': case 014: /* form feed */ cur = 1; break; case '\t': cur = ((cur - 1) & tabmask) + 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"); } } void writefdef(struct fstate *f, int nm) { fprintf(output, ".ds f%c %s\n.nr s%c %d\n", nm, f->font, nm, f->size); } char * chfont(struct fstate *of, struct fstate *nf, char *s) { if (of->font[0] != nf->font[0] || of->font[1] != nf->font[1]) { *s++ = '\\'; *s++ = 'f'; if (nf->font[1]) { *s++ = '('; *s++ = nf->font[0]; *s++ = nf->font[1]; } else *s++ = nf->font[0]; } if (nf->size != of->size) { *s++ = '\\'; *s++ = 's'; if (nf->size < of->size) { *s++ = '-'; *s++ = '0' + of->size - nf->size; } else { *s++ = '+'; *s++ = '0' + nf->size - of->size; } } return s; } void parsefont(struct fstate *f, const char *s0) { const char *s = s0; int sizedelta = 0; - bzero(f, sizeof *f); + memset(f, '\0', sizeof(*f)); while (*s) { if (isdigit(*s)) f->size = f->size * 10 + *s - '0'; else if (isupper(*s)) if (f->font[0]) f->font[1] = *s; else f->font[0] = *s; else if (*s == 'c') f->allcaps = 1; else if (*s == '+') sizedelta++; else if (*s == '-') sizedelta--; else { errx(1, "bad font specification: %s", s0); } s++; } if (f->font[0] == 0) f->font[0] = 'R'; if (bodyf.size == 0) bodyf.size = 11; if (f->size == 0) f->size = bodyf.size + sizedelta; else if (sizedelta > 0) f->size += bodyf.size; else f->size = bodyf.size - f->size; } Index: stable/11/usr.bin/indent/lexi.c =================================================================== --- stable/11/usr.bin/indent/lexi.c (revision 331146) +++ stable/11/usr.bin/indent/lexi.c (revision 331147) @@ -1,615 +1,644 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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 __FBSDID("$FreeBSD$"); /* * 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 #include #include #include #include #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; }; struct templ specials[1000] = { - {"switch", 1}, - {"case", 2}, - {"break", 0}, + {"switch", 7}, + {"case", 8}, + {"break", 9}, {"struct", 3}, {"union", 3}, {"enum", 3}, - {"default", 2}, + {"default", 8}, {"int", 4}, {"char", 4}, {"float", 4}, {"double", 4}, {"long", 4}, {"short", 4}, {"typedef", 4}, {"unsigned", 4}, {"register", 4}, {"static", 4}, {"global", 4}, {"extern", 4}, {"void", 4}, {"const", 4}, {"volatile", 4}, - {"goto", 0}, - {"return", 0}, + {"goto", 9}, + {"return", 9}, {"if", 5}, {"while", 5}, {"for", 5}, {"else", 6}, {"do", 6}, - {"sizeof", 7}, + {"sizeof", 2}, + {"offsetof", 1}, {0, 0} }; 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 }; int lexi(void) { int unary_delim; /* this is set to 1 if the current token * forces a following operator to be unary */ static int last_code; /* the last token type returned */ static int l_struct; /* set to 1 if the last token was 'struct' */ 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; ps.col_1 = ps.last_nl; /* tell world that this token started in * column 1 iff the last thing scanned was nl */ ps.last_nl = false; while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ ps.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[(int)*buf_ptr] == alphanum || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { /* * we have a character or number */ const char *j; /* used for searching thru list of * * reserved words */ struct templ *p; if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { + enum base { + BASE_2, BASE_8, BASE_10, BASE_16 + }; int seendot = 0, seenexp = 0, seensfx = 0; - if (*buf_ptr == '0' && - (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) { + enum base in_base = BASE_10; + + if (*buf_ptr == '0') { + if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B') + in_base = BASE_2; + else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X') + in_base = BASE_16; + else if (isdigit(buf_ptr[1])) + in_base = BASE_8; + } + switch (in_base) { + case BASE_2: *e_token++ = *buf_ptr++; *e_token++ = *buf_ptr++; + while (*buf_ptr == '0' || *buf_ptr == '1') { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + } + break; + case BASE_8: + *e_token++ = *buf_ptr++; + while (*buf_ptr >= '0' && *buf_ptr <= '8') { + CHECK_SIZE_TOKEN; + *e_token++ = *buf_ptr++; + } + break; + case BASE_16: + *e_token++ = *buf_ptr++; + *e_token++ = *buf_ptr++; while (isxdigit(*buf_ptr)) { CHECK_SIZE_TOKEN; *e_token++ = *buf_ptr++; } - } - else + break; + case BASE_10: while (1) { if (*buf_ptr == '.') { if (seendot) break; else seendot++; } CHECK_SIZE_TOKEN; *e_token++ = *buf_ptr++; if (!isdigit(*buf_ptr) && *buf_ptr != '.') { if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) break; else { seenexp++; seendot++; CHECK_SIZE_TOKEN; *e_token++ = *buf_ptr++; if (*buf_ptr == '+' || *buf_ptr == '-') *e_token++ = *buf_ptr++; } } } + break; + } while (1) { - if (!(seensfx & 1) && - (*buf_ptr == 'U' || *buf_ptr == 'u')) { + if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) { CHECK_SIZE_TOKEN; *e_token++ = *buf_ptr++; seensfx |= 1; continue; } - if (!(seensfx & 2) && - (*buf_ptr == 'L' || *buf_ptr == 'l')) { + if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) { CHECK_SIZE_TOKEN; if (buf_ptr[1] == buf_ptr[0]) *e_token++ = *buf_ptr++; *e_token++ = *buf_ptr++; seensfx |= 2; continue; } break; } } else while (chartype[(int)*buf_ptr] == 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; /* 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(); } - ps.its_a_keyword = false; - ps.sizeof_keyword = false; + ps.keyword = 0; if (l_struct && !ps.p_l_follow) { /* if last token was 'struct' and we're not * in parentheses, then this token * should be treated as a declaration */ l_struct = false; last_code = ident; ps.last_u_d = true; return (decl); } ps.last_u_d = l_struct; /* Operator after identifier is binary * unless last token was 'struct' */ l_struct = false; last_code = ident; /* Remember that this is the code we will * return */ if (auto_typedefs) { const char *q = s_token; size_t q_len = strlen(q); /* Check if we have an "_t" in the end */ if (q_len > 2 && (strcmp(q + q_len - 2, "_t") == 0)) { - ps.its_a_keyword = true; + ps.keyword = 4; /* a type name */ ps.last_u_d = true; goto found_auto_typedef; } } /* * This loop will check if the token is a keyword. */ - for (p = specials; (j = p->rwd) != 0; p++) { + for (p = specials; (j = p->rwd) != NULL; p++) { const char *q = s_token; /* point at scanned token */ if (*j++ != *q++ || *j++ != *q++) continue; /* This test depends on the fact that * identifiers are always at least 1 character * long (ie. the first two bytes of the * identifier are always meaningful) */ if (q[-1] == 0) break; /* If its a one-character identifier */ while (*q++ == *j) if (*j++ == 0) goto found_keyword; /* I wish that C had a multi-level * break... */ } if (p->rwd) { /* we have a keyword */ found_keyword: - ps.its_a_keyword = true; + ps.keyword = p->rwcode; ps.last_u_d = true; switch (p->rwcode) { - case 1: /* it is a switch */ + case 7: /* it is a switch */ return (swstmt); - case 2: /* a case or default */ + case 8: /* a case or default */ return (casestmt); case 3: /* a "struct" */ /* * Next time around, we will want to know that we have had a * 'struct' */ l_struct = true; /* FALLTHROUGH */ case 4: /* one of the declaration keywords */ found_auto_typedef: if (ps.p_l_follow) { - ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.sizeof_mask; - break; /* inside parens: cast, param list or sizeof */ + /* inside parens: cast, param list, offsetof or sizeof */ + ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.not_cast_mask; + break; } last_code = decl; return (decl); case 5: /* if, while, for */ return (sp_paren); case 6: /* do, else */ return (sp_nparen); - case 7: - ps.sizeof_keyword = true; default: /* all others are treated like any other * identifier */ return (ident); } /* end of switch */ } /* end of if (found_it) */ if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) { char *tp = buf_ptr; while (tp < buf_end) if (*tp++ == ')' && (*tp == ';' || *tp == ',')) goto not_proc; strncpy(ps.procname, token, sizeof ps.procname - 1); ps.in_parameter_declaration = 1; rparen_count = 1; not_proc:; } /* * The following hack attempts to guess whether or not the current * token is in fact a declaration keyword -- one that has been * typedefd */ if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_') && !ps.p_l_follow && !ps.block_init && (ps.last_token == rparen || ps.last_token == semicolon || ps.last_token == decl || ps.last_token == lbrace || ps.last_token == rbrace)) { - ps.its_a_keyword = true; + ps.keyword = 4; /* a type name */ ps.last_u_d = true; last_code = decl; return decl; } if (last_code == decl) /* if this is a declared variable, then * following sign is unary */ ps.last_u_d = true; /* will make "int a -1" work */ last_code = ident; return (ident); /* the ident is not in the list */ } /* end of procesing for alpanum character */ /* Scan a non-alphanumeric token */ *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 = ps.last_u_d; ps.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; if (troff) { e_token[-1] = '`'; if (qchar == '"') *e_token++ = '`'; e_token = chfont(&bodyf, &stringf, e_token); } do { /* copy the string */ while (1) { /* move one character or [/] */ if (*buf_ptr == '\n') { diag2(1, "Unterminated literal"); goto stop_lit; } CHECK_SIZE_TOKEN; /* Only have to do this once in this loop, * since CHECK_SIZE guarantees that there * are at least 5 entries left */ *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; if (troff) { *++e_token = BACKSLASH; if (*buf_ptr == BACKSLASH) *++e_token = BACKSLASH; } *++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); if (troff) { e_token = chfont(&stringf, &bodyf, e_token - 1); if (qchar == '"') *e_token++ = '\''; } stop_lit: code = ident; break; case ('('): case ('['): unary_delim = true; code = lparen; break; case (')'): case (']'): code = rparen; break; case '#': unary_delim = ps.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 (ps.in_or_st) ps.block_init = 1; */ /* ? code = ps.block_init ? lparen : lbrace; */ code = lbrace; break; case ('}'): unary_delim = true; /* ? code = ps.block_init ? rparen : rbrace; */ code = rbrace; break; case 014: /* a form feed */ unary_delim = ps.last_u_d; ps.last_nl = true; /* remember this so we can set 'ps.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 = (ps.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 (last_code == ident || last_code == rparen) { code = (ps.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++; if (!pointer_as_binop) { unary_delim = false; code = unary_op; ps.want_blank = false; } } break; /* buffer overflow will be checked at end of * switch */ case '=': if (ps.in_or_st) ps.block_init = 1; #ifdef undef if (chartype[*buf_ptr] == 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 = (ps.last_u_d ? unary_op : binary_op); unary_delim = true; 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 = ps.last_u_d; break; } while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { /* * handle ||, &&, etc, and also things as in int *****i */ *e_token++ = *buf_ptr; if (++buf_ptr >= buf_end) fill_buffer(); } code = (ps.last_u_d ? unary_op : binary_op); unary_delim = true; } /* end of switch */ if (code != newline) { l_struct = false; last_code = code; } if (buf_ptr >= buf_end) /* check for input buffer empty */ fill_buffer(); ps.last_u_d = unary_delim; *e_token = '\0'; /* null terminate the token */ return (code); } /* * Add the given keyword to the keyword table, using val as the keyword type */ void addkey(char *key, int val) { struct templ *p = specials; while (p->rwd) if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) return; else p++; if (p >= specials + sizeof specials / sizeof specials[0]) return; /* For now, table overflows are silently * ignored */ p->rwd = key; p->rwcode = val; - p[1].rwd = 0; + p[1].rwd = NULL; p[1].rwcode = 0; } Index: stable/11/usr.bin/indent/parse.c =================================================================== --- stable/11/usr.bin/indent/parse.c (revision 331146) +++ stable/11/usr.bin/indent/parse.c (revision 331147) @@ -1,334 +1,344 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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 __FBSDID("$FreeBSD$"); +#include #include #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 ..." */ - ps.i_l_follow = ps.il[ps.tos]; + /* + * 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 */ 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 or */ - if (ps.p_stack[ps.tos - 1] == lbrace) { + 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 >= STACKSIZE - 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 * * * do "dostmt" * if "ifstmt" * switch * decl * "ifelse" * for * while * "dostmt" while * * 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: /* */ ps.p_stack[--ps.tos] = dohead; ps.i_l_follow = ps.il[ps.tos]; break; case ifstmt: /* */ 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: /* */ case_ind = ps.cstk[ps.tos - 1]; - + /* FALLTHROUGH */ case decl: /* finish of a declaration */ case elsehead: /* < else> */ case forstmt: /* */ case whilestmt: /* */ ps.p_stack[--ps.tos] = stmt; ps.i_l_follow = ps.il[ps.tos]; break; default: /* */ return; } /* end of section for 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; } } } Index: stable/11/usr.bin/indent/pr_comment.c =================================================================== --- stable/11/usr.bin/indent/pr_comment.c (revision 331146) +++ stable/11/usr.bin/indent/pr_comment.c (revision 331147) @@ -1,431 +1,349 @@ -/* +/*- * SPDX-License-Identifier: BSD-4-Clause * * 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 __FBSDID("$FreeBSD$"); #include #include #include +#include #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 unix_comment; /* tri-state variable used to decide if it is - * a unix-style comment. 0 means only blanks - * since /+*, 1 means regular style comment, 2 - * means unix style comment */ int break_delim = comment_delimiter_on_blankline; int l_just_saw_decl = ps.just_saw_decl; - /* - * int ps.last_nl = 0; true iff the last significant thing - * weve seen is a newline - */ - int one_liner = 1; /* true iff this comment is a one-liner */ adj_max_col = max_col; ps.just_saw_decl = 0; - last_bl = 0; /* no blanks found so far */ + 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 */ - unix_comment = 1; /* set flag to let us figure out if there is a - * unix-style comment ** DISABLED: use 0 to - * reenable this hack! */ /* 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 = 0; + 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 = 0; + 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); } ps.com_col = ps.decl_on_line || ps.ind_level == 0 ? ps.decl_com_ind : ps.com_ind; - if (ps.com_col < target_col) + if (ps.com_col <= target_col) ps.com_col = ((target_col + 7) & ~7) + 1; if (ps.com_col + 24 > adj_max_col) adj_max_col = ps.com_col + 24; } } if (ps.box_com) { - buf_ptr[-2] = 0; - ps.n_comment_delta = 1 - count_spaces(1, in_buffer); - buf_ptr[-2] = '/'; + /* + * 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 = buf_ptr >= save_com && buf_ptr < save_com + sc_size ? bp_save : buf_ptr; + ps.n_comment_delta = 1 - count_spaces_until(1, in_buffer, start - 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++ = ' '; - *e_com = '\0'; - if (troff) { - now_col = 1; - adj_max_col = 80; + /* + * 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++ = ' '; } - else - now_col = count_spaces(ps.com_col, s_com); /* figure what column we - * would be in if we - * printed the comment - * now */ + if (troff) + adj_max_col = 80; + /* Start to copy the comment */ while (1) { /* this loop will go until the comment is * copied */ - if (*buf_ptr > 040 && *buf_ptr != '*') - ps.last_nl = 0; CHECK_SIZE_COM; switch (*buf_ptr) { /* this checks for various spcl cases */ case 014: /* check for a form feed */ 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 = 0; - *e_com++ = ' '; - *e_com++ = '*'; - *e_com++ = ' '; - while (*++buf_ptr == ' ' || *buf_ptr == '\t'); + 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"); - *e_com = '\0'; dump_line(); return; } - one_liner = 0; + last_bl = NULL; if (ps.box_com || ps.last_nl) { /* if this is a boxed comment, * we dont ignore the newline */ - if (s_com == e_com) { + if (s_com == e_com) *e_com++ = ' '; - *e_com++ = ' '; - } - *e_com = '\0'; if (!ps.box_com && e_com - s_com > 3) { - if (break_delim == 1 && s_com[0] == '/' - && s_com[1] == '*' && s_com[2] == ' ') { - char *t = e_com; - break_delim = 2; - e_com = s_com + 2; - *e_com = 0; - if (blanklines_before_blockcomments) - prefix_blankline_requested = 1; - dump_line(); - e_com = t; - s_com[0] = s_com[1] = s_com[2] = ' '; - } dump_line(); - CHECK_SIZE_COM; - *e_com++ = ' '; - *e_com++ = ' '; + if (star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; } dump_line(); - now_col = ps.com_col; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; } else { ps.last_nl = 1; - if (unix_comment != 1) { /* we not are in unix_style - * comment */ - if (unix_comment == 0 && s_code == e_code) { - /* - * if it is a UNIX-style comment, ignore the - * requirement that previous line be blank for - * unindention - */ - ps.com_col = (ps.ind_level - ps.unindent_displace) * ps.ind_size + 1; - if (ps.com_col <= 1) - ps.com_col = 2; - } - unix_comment = 2; /* permanently remember that we are in - * this type of comment */ - dump_line(); - ++line_no; - now_col = ps.com_col; - *e_com++ = ' '; - /* - * fix so that the star at the start of the line will line - * up - */ - do /* flush leading white space */ - if (++buf_ptr >= buf_end) - fill_buffer(); - while (*buf_ptr == ' ' || *buf_ptr == '\t'); - break; - } 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; CHECK_SIZE_COM; *e_com++ = ' '; - ++now_col; } } ++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(); - if (unix_comment == 0) /* set flag to show we are not in - * unix-style comment */ - unix_comment = 1; - if (*buf_ptr == '/') { /* it is the end!!! */ end_of_comment: if (++buf_ptr >= buf_end) fill_buffer(); - - if (*(e_com - 1) != ' ' && !ps.box_com) { /* insure blank before - * end */ + CHECK_SIZE_COM; + if (break_delim) { + if (e_com > s_com + 3) { + dump_line(); + } + else + s_com = e_com; *e_com++ = ' '; - ++now_col; } - if (break_delim == 1 && !one_liner && s_com[0] == '/' - && s_com[1] == '*' && s_com[2] == ' ') { - char *t = e_com; - break_delim = 2; - e_com = s_com + 2; - *e_com = 0; - if (blanklines_before_blockcomments) - prefix_blankline_requested = 1; - dump_line(); - e_com = t; - s_com[0] = s_com[1] = s_com[2] = ' '; - } - if (break_delim == 2 && e_com > s_com + 3 - /* now_col > adj_max_col - 2 && !ps.box_com */ ) { - *e_com = '\0'; - dump_line(); - now_col = ps.com_col; - } - CHECK_SIZE_COM; - *e_com++ = '*'; - *e_com++ = '/'; - *e_com = '\0'; + 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 '*' */ + else /* handle isolated '*' */ *e_com++ = '*'; - ++now_col; - } break; default: /* we have a random char */ - if (unix_comment == 0 && *buf_ptr != ' ' && *buf_ptr != '\t') - unix_comment = 1; /* we are not in unix-style comment */ - - *e_com = *buf_ptr++; - if (buf_ptr >= buf_end) - fill_buffer(); - - if (*e_com == '\t') /* keep track of column */ - now_col = ((now_col - 1) & tabmask) + tabsize + 1; - else if (*e_com == '\b') /* this is a backspace */ - --now_col; - else - ++now_col; - - if (*e_com == ' ' || *e_com == '\t') - last_bl = e_com; - /* remember we saw a blank */ - - ++e_com; - if (now_col > adj_max_col && !ps.box_com && unix_comment == 1 && e_com[-1] > ' ') { + now_col = count_spaces_until(ps.com_col, s_com, e_com); + do { + *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 (break_delim == 1 && s_com[0] == '/' - && s_com[1] == '*' && s_com[2] == ' ') { - char *t = e_com; - break_delim = 2; - e_com = s_com + 2; - *e_com = 0; - if (blanklines_before_blockcomments) - prefix_blankline_requested = 1; + if (last_bl == NULL) { dump_line(); - e_com = t; - s_com[0] = s_com[1] = s_com[2] = ' '; + if (!ps.box_com && star_comment_cont) + *e_com++ = ' ', *e_com++ = '*', *e_com++ = ' '; + break; } - if (last_bl == 0) { /* we have seen no blanks */ - last_bl = e_com; /* fake it */ - *e_com++ = ' '; - } - *e_com = '\0'; /* print what we have */ - *last_bl = '\0'; - while (last_bl > s_com && last_bl[-1] < 040) - *--last_bl = 0; + *e_com = '\0'; e_com = last_bl; dump_line(); - - *e_com++ = ' '; /* add blanks for continuation */ - *e_com++ = ' '; - *e_com++ = ' '; - - t_ptr = last_bl + 1; - last_bl = 0; - if (t_ptr >= e_com) { - while (*t_ptr == ' ' || *t_ptr == '\t') - t_ptr++; - while (*t_ptr != '\0') { /* move unprinted part of - * comment down in buffer */ - if (*t_ptr == ' ' || *t_ptr == '\t') - last_bl = e_com; - *e_com++ = *t_ptr++; - } - } - *e_com = '\0'; - now_col = count_spaces(ps.com_col, s_com); /* recompute current - * position */ + 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; + while (*t_ptr != '\0') { + if (*t_ptr == ' ' || *t_ptr == '\t') + last_bl = e_com; + *e_com++ = *t_ptr++; + } } break; } } } Index: stable/11/usr.bin/indent/tests/nsac.pro =================================================================== --- stable/11/usr.bin/indent/tests/nsac.pro (revision 331146) +++ stable/11/usr.bin/indent/tests/nsac.pro (nonexistent) @@ -1,2 +0,0 @@ -/* $FreeBSD$ */ --nsac Property changes on: stable/11/usr.bin/indent/tests/nsac.pro ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/label.pro =================================================================== --- stable/11/usr.bin/indent/tests/label.pro (revision 331146) +++ stable/11/usr.bin/indent/tests/label.pro (nonexistent) @@ -1,2 +0,0 @@ -/* $FreeBSD$ */ --nut Property changes on: stable/11/usr.bin/indent/tests/label.pro ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/elsecomment.pro =================================================================== --- stable/11/usr.bin/indent/tests/elsecomment.pro (revision 331146) +++ stable/11/usr.bin/indent/tests/elsecomment.pro (nonexistent) @@ -1,2 +0,0 @@ -/* $FreeBSD$ */ --bl Property changes on: stable/11/usr.bin/indent/tests/elsecomment.pro ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/surplusbad.pro =================================================================== --- stable/11/usr.bin/indent/tests/surplusbad.pro (revision 331146) +++ stable/11/usr.bin/indent/tests/surplusbad.pro (nonexistent) @@ -1,2 +0,0 @@ -/* $FreeBSD$ */ --bad Property changes on: stable/11/usr.bin/indent/tests/surplusbad.pro ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/types_from_file.list =================================================================== --- stable/11/usr.bin/indent/tests/types_from_file.list (revision 331146) +++ stable/11/usr.bin/indent/tests/types_from_file.list (nonexistent) @@ -1,2 +0,0 @@ -b -a \ No newline at end of file Property changes on: stable/11/usr.bin/indent/tests/types_from_file.list ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/sac.pro =================================================================== --- stable/11/usr.bin/indent/tests/sac.pro (revision 331146) +++ stable/11/usr.bin/indent/tests/sac.pro (nonexistent) @@ -1,2 +0,0 @@ -/* $FreeBSD$ */ --sac Property changes on: stable/11/usr.bin/indent/tests/sac.pro ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/types_from_file.pro =================================================================== --- stable/11/usr.bin/indent/tests/types_from_file.pro (revision 331146) +++ stable/11/usr.bin/indent/tests/types_from_file.pro (nonexistent) @@ -1,2 +0,0 @@ -/* $FreeBSD$ */ --Utypes_from_file.list Property changes on: stable/11/usr.bin/indent/tests/types_from_file.pro ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/Makefile =================================================================== --- stable/11/usr.bin/indent/tests/Makefile (nonexistent) +++ stable/11/usr.bin/indent/tests/Makefile (revision 331147) @@ -0,0 +1,45 @@ +# $FreeBSD$ + +PACKAGE= tests + +${PACKAGE}FILES+= binary.0 +${PACKAGE}FILES+= binary.0.stdout +${PACKAGE}FILES+= comments.0 +${PACKAGE}FILES+= comments.0.stdout +${PACKAGE}FILES+= declarations.0 +${PACKAGE}FILES+= declarations.0.stdout +${PACKAGE}FILES+= elsecomment.0 +${PACKAGE}FILES+= elsecomment.0.stdout +${PACKAGE}FILES+= elsecomment.0.pro +${PACKAGE}FILES+= float.0 +${PACKAGE}FILES+= float.0.stdout +${PACKAGE}FILES+= label.0 +${PACKAGE}FILES+= label.0.stdout +${PACKAGE}FILES+= label.0.pro +${PACKAGE}FILES+= list_head.0 +${PACKAGE}FILES+= list_head.0.stdout +${PACKAGE}FILES+= nsac.0 +${PACKAGE}FILES+= nsac.0.stdout +${PACKAGE}FILES+= nsac.0.pro +${PACKAGE}FILES+= offsetof.0 +${PACKAGE}FILES+= offsetof.0.stdout +${PACKAGE}FILES+= sac.0 +${PACKAGE}FILES+= sac.0.stdout +${PACKAGE}FILES+= sac.0.pro +${PACKAGE}FILES+= struct.0 +${PACKAGE}FILES+= struct.0.stdout +${PACKAGE}FILES+= surplusbad.0 +${PACKAGE}FILES+= surplusbad.0.stdout +${PACKAGE}FILES+= surplusbad.0.pro +${PACKAGE}FILES+= types_from_file.0 +${PACKAGE}FILES+= types_from_file.0.stdout +${PACKAGE}FILES+= types_from_file.0.list +${PACKAGE}FILES+= types_from_file.0.pro +${PACKAGE}FILES+= wchar.0 +${PACKAGE}FILES+= wchar.0.stdout + +ATF_TESTS_SH+= functional_test + +BINDIR= ${TESTSDIR} + +.include Property changes on: stable/11/usr.bin/indent/tests/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/binary.0 =================================================================== --- stable/11/usr.bin/indent/tests/binary.0 (nonexistent) +++ stable/11/usr.bin/indent/tests/binary.0 (revision 331147) @@ -0,0 +1,10 @@ +/* $FreeBSD$ */ +#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; +} Property changes on: stable/11/usr.bin/indent/tests/binary.0 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/11/usr.bin/indent/tests/binary.0.stdout =================================================================== --- stable/11/usr.bin/indent/tests/binary.0.stdout (nonexistent) +++ stable/11/usr.bin/indent/tests/binary.0.stdout (revision 331147) @@ -0,0 +1,12 @@ +/* $FreeBSD$ */ +#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; +} Property changes on: stable/11/usr.bin/indent/tests/binary.0.stdout ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/11/usr.bin/indent/tests/comments.0 =================================================================== --- stable/11/usr.bin/indent/tests/comments.0 (revision 331146) +++ stable/11/usr.bin/indent/tests/comments.0 (revision 331147) @@ -1,25 +1,32 @@ /* $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 */ } Index: stable/11/usr.bin/indent/tests/comments.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/comments.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/comments.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-bbb Property changes on: stable/11/usr.bin/indent/tests/comments.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/comments.0.stdout =================================================================== --- stable/11/usr.bin/indent/tests/comments.0.stdout (revision 331146) +++ stable/11/usr.bin/indent/tests/comments.0.stdout (revision 331147) @@ -1,32 +1,39 @@ /* $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 */ } Index: stable/11/usr.bin/indent/tests/elsecomment.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/elsecomment.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/elsecomment.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-bl Property changes on: stable/11/usr.bin/indent/tests/elsecomment.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/functional_test.sh =================================================================== --- stable/11/usr.bin/indent/tests/functional_test.sh (nonexistent) +++ stable/11/usr.bin/indent/tests/functional_test.sh (revision 331147) @@ -0,0 +1,90 @@ +# +# Copyright 2016 Dell EMC +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. +# +# $FreeBSD$ + +SRCDIR=$(atf_get_srcdir) + +check() +{ + local tc=${1}; shift + + local indent=$(atf_config_get usr.bin.indent.test_indent /usr/bin/indent) + + # All of the files need to be in the ATF sandbox in order for the tests + # to pass. + atf_check cp ${SRCDIR}/${tc}* . + + # Remove $FreeBSD$ RCS expansions because they get re-indented, which + # changes the output + local out_file="${tc}.stdout" + if [ -f "${out_file}" ]; then + parsed_file=output_file.parsed + + atf_check -o save:$parsed_file sed -e '/\$FreeBSD.*\$/d' \ + ${tc}.stdout + out_flag="-o file:$parsed_file" + fi + local profile_file="${tc}.pro" + if [ -f "${profile_file}" ]; then + profile_flag="-P${profile_file}" + else + # Make sure we don't implicitly use ~/.indent.pro from the test + # host, for determinism purposes. + profile_flag="-npro" + fi + sed -e '/\$FreeBSD.*\$/d' ${tc} > input_file.parsed + atf_check -s exit:${tc##*.} ${out_flag} ${indent} ${profile_flag} < input_file.parsed +} + +add_testcase() +{ + local tc=${1} + local tc_escaped word + + case "${tc%.*}" in + *-*) + local IFS="-" + for word in ${tc%.*}; do + tc_escaped="${tc_escaped:+${tc_escaped}_}${word}" + done + ;; + *) + tc_escaped=${tc%.*} + ;; + esac + + atf_test_case ${tc_escaped} + eval "${tc_escaped}_body() { check ${tc}; }" + atf_add_test_case ${tc_escaped} +} + +atf_init_test_cases() +{ + for path in $(find -Es "${SRCDIR}" -regex '.*\.[0-9]+$'); do + add_testcase ${path##*/} + done +} Property changes on: stable/11/usr.bin/indent/tests/functional_test.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/label.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/label.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/label.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-nut Property changes on: stable/11/usr.bin/indent/tests/label.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/nsac.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/nsac.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/nsac.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-nsac Property changes on: stable/11/usr.bin/indent/tests/nsac.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/sac.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/sac.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/sac.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-sac Property changes on: stable/11/usr.bin/indent/tests/sac.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/surplusbad.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/surplusbad.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/surplusbad.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-bad Property changes on: stable/11/usr.bin/indent/tests/surplusbad.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/types_from_file.0.list =================================================================== --- stable/11/usr.bin/indent/tests/types_from_file.0.list (nonexistent) +++ stable/11/usr.bin/indent/tests/types_from_file.0.list (revision 331147) @@ -0,0 +1,2 @@ +b +a \ No newline at end of file Property changes on: stable/11/usr.bin/indent/tests/types_from_file.0.list ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/usr.bin/indent/tests/types_from_file.0.pro =================================================================== --- stable/11/usr.bin/indent/tests/types_from_file.0.pro (nonexistent) +++ stable/11/usr.bin/indent/tests/types_from_file.0.pro (revision 331147) @@ -0,0 +1,2 @@ +/* $FreeBSD$ */ +-Utypes_from_file.0.list Property changes on: stable/11/usr.bin/indent/tests/types_from_file.0.pro ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11 =================================================================== --- stable/11 (revision 331146) +++ stable/11 (revision 331147) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r303452,303482-303485,303487,303489,303498-303499,303502,303523,303525,303570-303571,303588,303596-303601,303625,303629,303718,304651,304684,304686,305983,309217,309219,309341-309343,309382,309415,309417-309419,310863,311141,314613,318471,321382-321383,321396