indent.h revision 1.51 1 /* $NetBSD: indent.h,v 1.51 2021/10/26 19:36:30 rillig Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 2001 Jens Schweikhardt
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30 /*-
31 * SPDX-License-Identifier: BSD-4-Clause
32 *
33 * Copyright (c) 1985 Sun Microsystems, Inc.
34 * Copyright (c) 1980, 1993
35 * The Regents of the University of California. All rights reserved.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 */
66
67 #if 0
68 __FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 336333 2018-07-16 05:46:50Z pstef $");
69 #endif
70
71 #include <stdbool.h>
72
73 typedef enum lexer_symbol {
74 lsym_eof,
75 lsym_preprocessing, /* '#' */
76 lsym_newline,
77 lsym_form_feed,
78 lsym_comment,
79 lsym_lparen_or_lbracket,
80 lsym_rparen_or_rbracket,
81 lsym_lbrace,
82 lsym_rbrace,
83 lsym_period,
84 lsym_unary_op, /* e.g. '+' or '&' */
85 lsym_binary_op, /* e.g. '<<' or '+' or '&&' or '/=' */
86 lsym_postfix_op, /* trailing '++' or '--' */
87 lsym_question, /* the '?' from a '?:' expression */
88 lsym_colon,
89 lsym_comma,
90 lsym_semicolon,
91 lsym_typedef,
92 lsym_storage_class,
93 lsym_type,
94 lsym_tag, /* 'struct', 'union', 'enum' */
95 lsym_case_label,
96 lsym_string_prefix, /* 'L' */
97 lsym_ident, /* identifier, constant or string */
98 lsym_funcname,
99 lsym_do,
100 lsym_else,
101 lsym_for,
102 lsym_if,
103 lsym_switch,
104 lsym_while,
105 } lexer_symbol;
106
107 typedef enum parser_symbol {
108 psym_semicolon, /* rather a placeholder than a semicolon */
109 psym_lbrace,
110 psym_rbrace,
111 psym_decl,
112 psym_stmt,
113 psym_stmt_list,
114 psym_for_exprs, /* 'for' '(' ... ')' */
115 psym_if_expr, /* 'if' '(' expr ')' */
116 psym_if_expr_stmt, /* 'if' '(' expr ')' stmt */
117 psym_if_expr_stmt_else, /* 'if' '(' expr ')' stmt 'else' */
118 psym_else, /* 'else' */
119 psym_switch_expr, /* 'switch' '(' expr ')' */
120 psym_do, /* 'do' */
121 psym_do_stmt, /* 'do' stmt */
122 psym_while_expr, /* 'while' '(' expr ')' */
123 } parser_symbol;
124
125 typedef enum stmt_head {
126 hd_0, /* placeholder for uninitialized */
127 hd_for,
128 hd_if,
129 hd_switch,
130 hd_while,
131 } stmt_head;
132
133 #define sc_size 5000 /* size of save_com buffer */
134 #define label_offset 2 /* number of levels a label is placed to left
135 * of code */
136
137
138 struct buffer {
139 char *buf; /* buffer */
140 char *s; /* start */
141 char *e; /* end */
142 char *l; /* limit */
143 };
144
145 extern FILE *input;
146 extern FILE *output;
147
148 extern struct buffer lab; /* label or preprocessor directive */
149 extern struct buffer code; /* code */
150 extern struct buffer com; /* comment */
151 extern struct buffer token; /* the last token scanned */
152
153 extern struct buffer inp;
154
155 extern char sc_buf[sc_size]; /* input text is saved here when looking for
156 * the brace after an if, while, etc */
157 extern char *save_com; /* start of the comment stored in sc_buf */
158
159 extern char *saved_inp_s; /* saved value of inp.s when taking input from
160 * save_com */
161 extern char *saved_inp_e; /* similarly saved value of inp.e */
162
163
164 extern struct options {
165 bool blanklines_around_conditional_compilation;
166 bool blanklines_after_decl_at_top; /* this is vaguely similar to
167 * blanklines_after_decl except that
168 * it only applies to the first set of
169 * declarations in a procedure (just
170 * after the first '{') and it causes
171 * a blank line to be generated even
172 * if there are no declarations */
173 bool blanklines_after_decl;
174 bool blanklines_after_procs;
175 bool blanklines_before_block_comments;
176 bool break_after_comma; /* whether to break declarations after commas */
177 bool brace_same_line; /* whether brace should be on same line as if,
178 * while, etc */
179 bool blank_after_sizeof; /* whether a blank should always be inserted
180 * after sizeof */
181 bool comment_delimiter_on_blankline;
182 int decl_comment_column; /* the column in which comments after
183 * declarations should be put */
184 bool cuddle_else; /* whether 'else' should cuddle up to '}' */
185 int continuation_indent; /* the indentation between the edge of code
186 * and continuation lines */
187 float case_indent; /* The distance (measured in indentation
188 * levels) to indent case labels from the
189 * switch statement */
190 int comment_column; /* the column in which comments to the right
191 * of code should start */
192 int decl_indent; /* indentation of identifier in declaration */
193 bool ljust_decl; /* true if declarations should be left
194 * justified */
195 int unindent_displace; /* comments not to the right of code will be
196 * placed this many indentation levels to the
197 * left of code */
198 bool extra_expr_indent; /* whether continuation lines from the
199 * expression part of "if(e)", "while(e)",
200 * "for(e;e;e)" should be indented an extra
201 * tab stop so that they don't conflict with
202 * the code that follows */
203 bool else_if; /* whether else-if pairs should be handled
204 * specially */
205 bool function_brace_split; /* split function declaration and brace onto
206 * separate lines */
207 bool format_col1_comments; /* If comments which start in column 1 are to
208 * be magically reformatted (just like
209 * comments that begin in later columns) */
210 bool format_block_comments; /* whether comments beginning with '/ * \n'
211 * are to be reformatted */
212 bool indent_parameters;
213 int indent_size; /* the size of one indentation level */
214 int block_comment_max_line_length;
215 int local_decl_indent; /* like decl_indent but for locals */
216 bool lineup_to_parens_always; /* whether to not(?) attempt to keep
217 * lined-up code within the margin */
218 bool lineup_to_parens; /* whether continued code within parens will
219 * be lined up to the open paren */
220 bool proc_calls_space; /* whether function calls look like: foo (bar)
221 * rather than foo(bar) */
222 bool procnames_start_line; /* whether the names of procedures being
223 * defined get placed in column 1 (i.e. a
224 * newline is placed between the type of the
225 * procedure and its name) */
226 bool space_after_cast; /* "b = (int) a" vs "b = (int)a" */
227 bool star_comment_cont; /* whether comment continuation lines should
228 * have stars at the beginning of each line. */
229 bool swallow_optional_blanklines;
230 bool auto_typedefs; /* whether to recognize identifiers ending in
231 * "_t" like typedefs */
232 int tabsize; /* the size of a tab */
233 int max_line_length;
234 bool use_tabs; /* set true to use tabs for spacing, false
235 * uses all spaces */
236 bool verbose; /* whether non-essential error messages are
237 * printed */
238 } opt;
239
240 enum keyword_kind {
241 kw_0,
242 kw_offsetof,
243 kw_sizeof,
244 kw_struct_or_union_or_enum,
245 kw_type,
246 kw_for,
247 kw_if,
248 kw_while,
249 kw_do,
250 kw_else,
251 kw_switch,
252 kw_case_or_default,
253 kw_jump,
254 kw_storage_class,
255 kw_typedef,
256 kw_inline_or_restrict
257 };
258
259
260 extern bool found_err;
261 extern int blank_lines_to_output;
262 extern bool blank_line_before;
263 extern bool blank_line_after;
264 extern bool break_comma; /* when true and not in parens, break after a
265 * comma */
266 extern float case_ind; /* indentation level to be used for a "case
267 * n:" */
268 extern bool had_eof; /* whether input is exhausted */
269 extern int line_no; /* the current line number. */
270 extern bool inhibit_formatting; /* true if INDENT OFF is in effect */
271
272 #define STACKSIZE 256
273
274 /* TODO: group the members by purpose, don't sort them alphabetically */
275 extern struct parser_state {
276 lexer_symbol last_token;
277
278 int tos; /* pointer to top of stack */
279 parser_symbol s_sym[STACKSIZE];
280 int s_ind_level[STACKSIZE];
281 float s_case_ind_level[STACKSIZE];
282
283 int comment_delta; /* used to set up indentation for all lines of
284 * a boxed comment after the first one */
285 int n_comment_delta; /* remembers how many columns there were
286 * before the start of a box comment so that
287 * forthcoming lines of the comment are
288 * indented properly */
289 int cast_mask; /* indicates which close parens potentially
290 * close off casts */
291 int not_cast_mask; /* indicates which close parens definitely
292 * close off something else than casts */
293 bool block_init; /* whether inside a block initialization */
294 int block_init_level; /* The level of brace nesting in an
295 * initialization */
296 bool last_nl; /* whether the last thing scanned was a
297 * newline */
298 bool init_or_struct; /* whether there has been a declarator (e.g.
299 * int or char) and no left parenthesis since
300 * the last semicolon. When true, a '{' is
301 * starting a structure definition or an
302 * initialization list */
303 bool col_1; /* whether the last token started in column 1 */
304 int com_ind; /* indentation of the current comment */
305 int decl_nest; /* current nesting level for structure or init */
306 bool decl_on_line; /* whether this line of code has part of a
307 * declaration on it */
308 int ind_level_follow; /* the level to which ind_level should be set
309 * after the current line is printed */
310 bool in_decl; /* whether we are in a declaration stmt. The
311 * processing of braces is then slightly
312 * different */
313 bool in_stmt;
314 int ind_level; /* the current indentation level */
315 bool ind_stmt; /* whether the next line should have an extra
316 * indentation level because we are in the
317 * middle of a stmt */
318 bool next_unary; /* whether the following operator should be
319 * unary */
320 int p_l_follow; /* used to remember how to indent the
321 * following statement */
322 int paren_level; /* parenthesization level. used to indent
323 * within statements */
324 short paren_indents[20]; /* indentation of the operand/argument of each
325 * level of parentheses or brackets, relative
326 * to the enclosing statement */
327 bool is_case_label; /* 'case' and 'default' labels are indented
328 * differently from regular labels */
329 bool search_stmt; /* whether it is necessary to buffer up all
330 * text up to the start of a statement after
331 * an 'if', 'while', etc. */
332 bool want_blank; /* whether the following token should be
333 * prefixed by a blank. (Said prefixing is
334 * ignored in some cases.) */
335 enum keyword_kind keyword;
336 bool dumped_decl_indent;
337 bool in_parameter_declaration;
338 char procname[100]; /* The name of the current procedure */
339 int just_saw_decl;
340
341 struct {
342 int comments;
343 int lines;
344 int code_lines;
345 int comment_lines;
346 } stats;
347 } ps;
348
349
350 #define array_length(array) (sizeof (array) / sizeof (array[0]))
351
352 void add_typename(const char *);
353 int compute_code_indent(void);
354 int compute_label_indent(void);
355 int indentation_after_range(int, const char *, const char *);
356 int indentation_after(int, const char *);
357 #ifdef debug
358 void
359 debug_vis_range(const char *, const char *, const char *,
360 const char *);
361 void debug_printf(const char *, ...)__printflike(1, 2);
362 void debug_println(const char *, ...)__printflike(1, 2);
363 #else
364 #define debug_printf(fmt, ...) do { } while (false)
365 #define debug_println(fmt, ...) do { } while (false)
366 #define debug_vis_range(prefix, s, e, suffix) do { } while (false)
367 #endif
368 void inbuf_skip(void);
369 char inbuf_next(void);
370 lexer_symbol lexi(struct parser_state *);
371 void diag(int, const char *, ...)__printflike(2, 3);
372 void dump_line(void);
373 void dump_line_ff(void);
374 void inbuf_read_line(void);
375 void parse(parser_symbol);
376 void parse_hd(stmt_head);
377 void process_comment(void);
378 void set_option(const char *, const char *);
379 void load_profiles(const char *);
380
381 void *xmalloc(size_t);
382 void *xrealloc(void *, size_t);
383 char *xstrdup(const char *);
384
385 void buf_expand(struct buffer *, size_t);
386
387 static inline bool
388 is_hspace(char ch)
389 {
390 return ch == ' ' || ch == '\t';
391 }
392
393 static inline int
394 next_tab(int ind)
395 {
396 return ind - ind % opt.tabsize + opt.tabsize;
397 }
398