11590Srgrimes/*
21590Srgrimes * Copyright (c) 1985 Sun Microsystems, Inc.
31590Srgrimes * Copyright (c) 1980, 1993
41590Srgrimes *	The Regents of the University of California.  All rights reserved.
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * Redistribution and use in source and binary forms, with or without
81590Srgrimes * modification, are permitted provided that the following conditions
91590Srgrimes * are met:
101590Srgrimes * 1. Redistributions of source code must retain the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer.
121590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131590Srgrimes *    notice, this list of conditions and the following disclaimer in the
141590Srgrimes *    documentation and/or other materials provided with the distribution.
151590Srgrimes * 3. All advertising materials mentioning features or use of this software
161590Srgrimes *    must display the following acknowledgement:
171590Srgrimes *	This product includes software developed by the University of
181590Srgrimes *	California, Berkeley and its contributors.
191590Srgrimes * 4. Neither the name of the University nor the names of its contributors
201590Srgrimes *    may be used to endorse or promote products derived from this software
211590Srgrimes *    without specific prior written permission.
221590Srgrimes *
231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
241590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
251590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
271590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
301590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
311590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
321590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
331590Srgrimes * SUCH DAMAGE.
341590Srgrimes */
351590Srgrimes
36116390Scharnier#if 0
371590Srgrimes#ifndef lint
381590Srgrimesstatic char sccsid[] = "@(#)args.c	8.1 (Berkeley) 6/6/93";
39116390Scharnier#endif /* not lint */
4027419Scharnier#endif
41116390Scharnier
4299112Sobrien#include <sys/cdefs.h>
4399112Sobrien__FBSDID("$FreeBSD$");
441590Srgrimes
451590Srgrimes/*
461590Srgrimes * Argument scanning and profile reading code.  Default parameters are set
471590Srgrimes * here as well.
481590Srgrimes */
491590Srgrimes
5027419Scharnier#include <ctype.h>
5127419Scharnier#include <err.h>
52135477Sdas#include <limits.h>
531590Srgrimes#include <stdio.h>
541590Srgrimes#include <stdlib.h>
551590Srgrimes#include <string.h>
561590Srgrimes#include "indent_globs.h"
5785632Sschweikh#include "indent.h"
581590Srgrimes
591590Srgrimes/* profile types */
601590Srgrimes#define	PRO_SPECIAL	1	/* special case */
611590Srgrimes#define	PRO_BOOL	2	/* boolean */
621590Srgrimes#define	PRO_INT		3	/* integer */
631590Srgrimes#define PRO_FONT	4	/* troff font */
641590Srgrimes
651590Srgrimes/* profile specials for booleans */
661590Srgrimes#define	ON		1	/* turn it on */
671590Srgrimes#define	OFF		0	/* turn it off */
681590Srgrimes
691590Srgrimes/* profile specials for specials */
701590Srgrimes#define	IGN		1	/* ignore it */
711590Srgrimes#define	CLI		2	/* case label indent (float) */
721590Srgrimes#define	STDIN		3	/* use stdin */
731590Srgrimes#define	KEY		4	/* type (keyword) */
741590Srgrimes
7585632Sschweikhstatic void scan_profile(FILE *);
7685632Sschweikh
7793440Sdwmaloneconst char *option_source = "?";
781590Srgrimes
791590Srgrimes/*
801590Srgrimes * N.B.: because of the way the table here is scanned, options whose names are
811590Srgrimes * substrings of other options must occur later; that is, with -lp vs -l, -lp
821590Srgrimes * must be first.  Also, while (most) booleans occur more than once, the last
831590Srgrimes * default value is the one actually assigned.
841590Srgrimes */
851590Srgrimesstruct pro {
86116390Scharnier    const char *p_name;		/* name, e.g. -bl, -cli */
871590Srgrimes    int         p_type;		/* type (int, bool, special) */
881590Srgrimes    int         p_default;	/* the default value (if int) */
891590Srgrimes    int         p_special;	/* depends on type */
901590Srgrimes    int        *p_obj;		/* the associated variable */
911590Srgrimes}           pro[] = {
921590Srgrimes
9385632Sschweikh    {"T", PRO_SPECIAL, 0, KEY, 0},
9485632Sschweikh    {"bacc", PRO_BOOL, false, ON, &blanklines_around_conditional_compilation},
9585632Sschweikh    {"badp", PRO_BOOL, false, ON, &blanklines_after_declarations_at_proctop},
9685632Sschweikh    {"bad", PRO_BOOL, false, ON, &blanklines_after_declarations},
9785632Sschweikh    {"bap", PRO_BOOL, false, ON, &blanklines_after_procs},
9885632Sschweikh    {"bbb", PRO_BOOL, false, ON, &blanklines_before_blockcomments},
9985632Sschweikh    {"bc", PRO_BOOL, true, OFF, &ps.leave_comma},
10085632Sschweikh    {"bl", PRO_BOOL, true, OFF, &btype_2},
10185632Sschweikh    {"br", PRO_BOOL, true, ON, &btype_2},
10285632Sschweikh    {"bs", PRO_BOOL, false, ON, &Bill_Shannon},
10385632Sschweikh    {"cdb", PRO_BOOL, true, ON, &comment_delimiter_on_blankline},
10485632Sschweikh    {"cd", PRO_INT, 0, 0, &ps.decl_com_ind},
10585632Sschweikh    {"ce", PRO_BOOL, true, ON, &cuddle_else},
10685632Sschweikh    {"ci", PRO_INT, 0, 0, &continuation_indent},
10785632Sschweikh    {"cli", PRO_SPECIAL, 0, CLI, 0},
10885632Sschweikh    {"c", PRO_INT, 33, 0, &ps.com_ind},
10985632Sschweikh    {"di", PRO_INT, 16, 0, &ps.decl_indent},
11085632Sschweikh    {"dj", PRO_BOOL, false, ON, &ps.ljust_decl},
11185632Sschweikh    {"d", PRO_INT, 0, 0, &ps.unindent_displace},
11285632Sschweikh    {"eei", PRO_BOOL, false, ON, &extra_expression_indent},
11385632Sschweikh    {"ei", PRO_BOOL, true, ON, &ps.else_if},
11485632Sschweikh    {"fbc", PRO_FONT, 0, 0, (int *) &blkcomf},
115131184Sschweikh    {"fbs", PRO_BOOL, true, ON, &function_brace_split},
11685632Sschweikh    {"fbx", PRO_FONT, 0, 0, (int *) &boxcomf},
11785632Sschweikh    {"fb", PRO_FONT, 0, 0, (int *) &bodyf},
11885632Sschweikh    {"fc1", PRO_BOOL, true, ON, &format_col1_comments},
11985632Sschweikh    {"fcb", PRO_BOOL, true, ON, &format_block_comments},
12085632Sschweikh    {"fc", PRO_FONT, 0, 0, (int *) &scomf},
12185632Sschweikh    {"fk", PRO_FONT, 0, 0, (int *) &keywordf},
12285632Sschweikh    {"fs", PRO_FONT, 0, 0, (int *) &stringf},
12385632Sschweikh    {"ip", PRO_BOOL, true, ON, &ps.indent_parameters},
12485632Sschweikh    {"i", PRO_INT, 8, 0, &ps.ind_size},
12585632Sschweikh    {"lc", PRO_INT, 0, 0, &block_comment_max_col},
126125633Sbde    {"ldi", PRO_INT, -1, 0, &ps.local_decl_indent},
12785632Sschweikh    {"lp", PRO_BOOL, true, ON, &lineup_to_parens},
12885632Sschweikh    {"l", PRO_INT, 78, 0, &max_col},
12985632Sschweikh    {"nbacc", PRO_BOOL, false, OFF, &blanklines_around_conditional_compilation},
13085632Sschweikh    {"nbadp", PRO_BOOL, false, OFF, &blanklines_after_declarations_at_proctop},
13185632Sschweikh    {"nbad", PRO_BOOL, false, OFF, &blanklines_after_declarations},
13285632Sschweikh    {"nbap", PRO_BOOL, false, OFF, &blanklines_after_procs},
13385632Sschweikh    {"nbbb", PRO_BOOL, false, OFF, &blanklines_before_blockcomments},
13485632Sschweikh    {"nbc", PRO_BOOL, true, ON, &ps.leave_comma},
13585632Sschweikh    {"nbs", PRO_BOOL, false, OFF, &Bill_Shannon},
13685632Sschweikh    {"ncdb", PRO_BOOL, true, OFF, &comment_delimiter_on_blankline},
13785632Sschweikh    {"nce", PRO_BOOL, true, OFF, &cuddle_else},
13885632Sschweikh    {"ndj", PRO_BOOL, false, OFF, &ps.ljust_decl},
13985632Sschweikh    {"neei", PRO_BOOL, false, OFF, &extra_expression_indent},
14085632Sschweikh    {"nei", PRO_BOOL, true, OFF, &ps.else_if},
141131184Sschweikh    {"nfbs", PRO_BOOL, true, OFF, &function_brace_split},
14285632Sschweikh    {"nfc1", PRO_BOOL, true, OFF, &format_col1_comments},
14385632Sschweikh    {"nfcb", PRO_BOOL, true, OFF, &format_block_comments},
14485632Sschweikh    {"nip", PRO_BOOL, true, OFF, &ps.indent_parameters},
14585632Sschweikh    {"nlp", PRO_BOOL, true, OFF, &lineup_to_parens},
14685632Sschweikh    {"npcs", PRO_BOOL, false, OFF, &proc_calls_space},
14785632Sschweikh    {"npro", PRO_SPECIAL, 0, IGN, 0},
14885632Sschweikh    {"npsl", PRO_BOOL, true, OFF, &procnames_start_line},
14985632Sschweikh    {"nps", PRO_BOOL, false, OFF, &pointer_as_binop},
15085632Sschweikh    {"nsc", PRO_BOOL, true, OFF, &star_comment_cont},
15185632Sschweikh    {"nsob", PRO_BOOL, false, OFF, &swallow_optional_blanklines},
152131184Sschweikh    {"nut", PRO_BOOL, true, OFF, &use_tabs},
15385632Sschweikh    {"nv", PRO_BOOL, false, OFF, &verbose},
15485632Sschweikh    {"pcs", PRO_BOOL, false, ON, &proc_calls_space},
15585632Sschweikh    {"psl", PRO_BOOL, true, ON, &procnames_start_line},
15685632Sschweikh    {"ps", PRO_BOOL, false, ON, &pointer_as_binop},
15785632Sschweikh    {"sc", PRO_BOOL, true, ON, &star_comment_cont},
15885632Sschweikh    {"sob", PRO_BOOL, false, ON, &swallow_optional_blanklines},
15985632Sschweikh    {"st", PRO_SPECIAL, 0, STDIN, 0},
160205989Savg    {"ta", PRO_BOOL, false, ON, &auto_typedefs},
16185632Sschweikh    {"troff", PRO_BOOL, false, ON, &troff},
162131184Sschweikh    {"ut", PRO_BOOL, true, ON, &use_tabs},
16385632Sschweikh    {"v", PRO_BOOL, false, ON, &verbose},
1641590Srgrimes    /* whew! */
16585632Sschweikh    {0, 0, 0, 0, 0}
1661590Srgrimes};
1671590Srgrimes
1681590Srgrimes/*
1691590Srgrimes * set_profile reads $HOME/.indent.pro and ./.indent.pro and handles arguments
1701590Srgrimes * given in these files.
1711590Srgrimes */
17285632Sschweikhvoid
17385632Sschweikhset_profile(void)
1741590Srgrimes{
17598771Sjmallett    FILE *f;
176135477Sdas    char fname[PATH_MAX];
1771590Srgrimes    static char prof[] = ".indent.pro";
1781590Srgrimes
179135477Sdas    snprintf(fname, sizeof(fname), "%s/%s", getenv("HOME"), prof);
1801590Srgrimes    if ((f = fopen(option_source = fname, "r")) != NULL) {
1811590Srgrimes	scan_profile(f);
1821590Srgrimes	(void) fclose(f);
1831590Srgrimes    }
1841590Srgrimes    if ((f = fopen(option_source = prof, "r")) != NULL) {
1851590Srgrimes	scan_profile(f);
1861590Srgrimes	(void) fclose(f);
1871590Srgrimes    }
1881590Srgrimes    option_source = "Command line";
1891590Srgrimes}
1901590Srgrimes
19185632Sschweikhstatic void
19298771Sjmallettscan_profile(FILE *f)
1931590Srgrimes{
194127256Sdes    int		comment, i;
195127256Sdes    char	*p;
1961590Srgrimes    char        buf[BUFSIZ];
1971590Srgrimes
1981590Srgrimes    while (1) {
199127256Sdes	p = buf;
200127256Sdes	comment = 0;
201127256Sdes	while ((i = getc(f)) != EOF) {
202127256Sdes	    if (i == '*' && !comment && p > buf && p[-1] == '/') {
203127256Sdes		comment = p - buf;
204127256Sdes		*p++ = i;
205127256Sdes	    } else if (i == '/' && comment && p > buf && p[-1] == '*') {
206127256Sdes		p = buf + comment - 1;
207127256Sdes		comment = 0;
208127256Sdes	    } else if (isspace(i)) {
209127256Sdes		if (p > buf && !comment)
210127256Sdes		    break;
211127256Sdes	    } else {
212127256Sdes		*p++ = i;
213127256Sdes	    }
214127256Sdes	}
2151590Srgrimes	if (p != buf) {
2161590Srgrimes	    *p++ = 0;
2171590Srgrimes	    if (verbose)
2181590Srgrimes		printf("profile: %s\n", buf);
2191590Srgrimes	    set_option(buf);
2201590Srgrimes	}
2211590Srgrimes	else if (i == EOF)
2221590Srgrimes	    return;
2231590Srgrimes    }
2241590Srgrimes}
2251590Srgrimes
22693440Sdwmaloneconst char	*param_start;
2271590Srgrimes
22885632Sschweikhstatic int
22993440Sdwmaloneeqin(const char *s1, const char *s2)
2301590Srgrimes{
2311590Srgrimes    while (*s1) {
2321590Srgrimes	if (*s1++ != *s2++)
2331590Srgrimes	    return (false);
2341590Srgrimes    }
2351590Srgrimes    param_start = s2;
2361590Srgrimes    return (true);
2371590Srgrimes}
2381590Srgrimes
2391590Srgrimes/*
2401590Srgrimes * Set the defaults.
2411590Srgrimes */
24285632Sschweikhvoid
24385632Sschweikhset_defaults(void)
2441590Srgrimes{
24598771Sjmallett    struct pro *p;
2461590Srgrimes
2471590Srgrimes    /*
2481590Srgrimes     * Because ps.case_indent is a float, we can't initialize it from the
2491590Srgrimes     * table:
2501590Srgrimes     */
2511590Srgrimes    ps.case_indent = 0.0;	/* -cli0.0 */
2521590Srgrimes    for (p = pro; p->p_name; p++)
2531590Srgrimes	if (p->p_type != PRO_SPECIAL && p->p_type != PRO_FONT)
2541590Srgrimes	    *p->p_obj = p->p_default;
2551590Srgrimes}
2561590Srgrimes
25785632Sschweikhvoid
25885632Sschweikhset_option(char *arg)
2591590Srgrimes{
26098771Sjmallett    struct pro *p;
2611590Srgrimes
2621590Srgrimes    arg++;			/* ignore leading "-" */
2631590Srgrimes    for (p = pro; p->p_name; p++)
2641590Srgrimes	if (*p->p_name == *arg && eqin(p->p_name, arg))
2651590Srgrimes	    goto found;
26627419Scharnier    errx(1, "%s: unknown parameter \"%s\"", option_source, arg - 1);
2671590Srgrimesfound:
2681590Srgrimes    switch (p->p_type) {
2691590Srgrimes
2701590Srgrimes    case PRO_SPECIAL:
2711590Srgrimes	switch (p->p_special) {
2721590Srgrimes
2731590Srgrimes	case IGN:
2741590Srgrimes	    break;
2751590Srgrimes
2761590Srgrimes	case CLI:
2771590Srgrimes	    if (*param_start == 0)
2781590Srgrimes		goto need_param;
2791590Srgrimes	    ps.case_indent = atof(param_start);
2801590Srgrimes	    break;
2811590Srgrimes
2821590Srgrimes	case STDIN:
2831590Srgrimes	    if (input == 0)
2841590Srgrimes		input = stdin;
2851590Srgrimes	    if (output == 0)
2861590Srgrimes		output = stdout;
2871590Srgrimes	    break;
2881590Srgrimes
2891590Srgrimes	case KEY:
2901590Srgrimes	    if (*param_start == 0)
2911590Srgrimes		goto need_param;
2921590Srgrimes	    {
293135477Sdas		char *str = strdup(param_start);
294116390Scharnier		if (str == NULL)
295116390Scharnier			err(1, NULL);
2961590Srgrimes		addkey(str, 4);
2971590Srgrimes	    }
2981590Srgrimes	    break;
2991590Srgrimes
3001590Srgrimes	default:
30127419Scharnier	    errx(1, "set_option: internal error: p_special %d", p->p_special);
3021590Srgrimes	}
3031590Srgrimes	break;
3041590Srgrimes
3051590Srgrimes    case PRO_BOOL:
3061590Srgrimes	if (p->p_special == OFF)
3071590Srgrimes	    *p->p_obj = false;
3081590Srgrimes	else
3091590Srgrimes	    *p->p_obj = true;
3101590Srgrimes	break;
3111590Srgrimes
3121590Srgrimes    case PRO_INT:
3131590Srgrimes	if (!isdigit(*param_start)) {
3141590Srgrimes    need_param:
31527419Scharnier	    errx(1, "%s: ``%s'' requires a parameter", option_source, arg - 1);
3161590Srgrimes	}
3171590Srgrimes	*p->p_obj = atoi(param_start);
3181590Srgrimes	break;
3191590Srgrimes
3201590Srgrimes    case PRO_FONT:
3211590Srgrimes	parsefont((struct fstate *) p->p_obj, param_start);
3221590Srgrimes	break;
3231590Srgrimes
3241590Srgrimes    default:
32527419Scharnier	errx(1, "set_option: internal error: p_type %d", p->p_type);
3261590Srgrimes    }
3271590Srgrimes}
328