fmt_decl.c revision 1.25 1 /* $NetBSD: fmt_decl.c,v 1.25 2021/11/25 16:05:07 rillig Exp $ */
2 /* $FreeBSD: head/usr.bin/indent/tests/declarations.0 334478 2018-06-01 09:41:15Z pstef $ */
3
4 /*
5 * Tests for declarations of global variables, external functions, and local
6 * variables.
7 *
8 * See also:
9 * opt_di.c
10 */
11
12 /* See FreeBSD r303570 */
13
14 /*
15 * A type definition usually declares a single type, so there is no need to
16 * align the newly declared type name with the other variables.
17 */
18 #indent input
19 typedef void ( * voidptr ) ( int * ) ;
20 #indent end
21
22 #indent run
23 typedef void (*voidptr)(int *);
24 #indent end
25
26
27 /*
28 * In variable declarations, the names of the first declarators are indented
29 * by the amount given in '-di', which defaults to 16.
30 */
31 #indent input
32 extern void ( * function_pointer ) ( int * ) ;
33 extern void * pointer;
34 #indent end
35
36 #indent run
37 /* $ XXX: Why is the token 'function_pointer' not aligned with 'pointer'? */
38 extern void (*function_pointer)(int *);
39 extern void *pointer;
40 #indent end
41
42
43 #indent input
44 static const struct
45 {
46 double x;
47 double y, z;
48 } n[m + 1] =
49 {
50 {
51 .0,
52 .9,
53 5
54 }
55 };
56 #indent end
57
58 #indent run
59 static const struct {
60 double x;
61 double y, z;
62 } n[m + 1] =
63 {
64 {
65 .0,
66 .9,
67 5
68 }
69 };
70 #indent end
71
72
73 #indent input
74 typedef struct Complex
75 {
76 double x;
77 double y;
78 } Complex;
79 #indent end
80
81 #indent run
82 typedef struct Complex {
83 double x;
84 double y;
85 } Complex;
86 #indent end
87
88
89 /*
90 * As of 2021-11-07, indent parses the following function definition as these
91 * tokens:
92 *
93 * line 1: type_outside_parentheses "void"
94 * line 1: newline "\n"
95 * line 2: funcname "t1"
96 * line 2: newline "\n" repeated, see search_stmt
97 * line 3: funcname "t1" XXX: wrong line_no
98 * line 3: lparen_or_lbracket "("
99 * line 3: type_in_parentheses "char"
100 * line 3: unary_op "*"
101 * line 3: word "a"
102 * line 3: comma ","
103 * line 3: type_in_parentheses "int"
104 * line 3: word "b"
105 * line 3: comma ","
106 * line 3: newline "\n"
107 * line 4: type_in_parentheses "void"
108 * line 4: lparen_or_lbracket "("
109 * line 4: unary_op "*"
110 * line 4: word "fn"
111 * line 4: rparen_or_rbracket ")"
112 * line 4: lparen_or_lbracket "("
113 * line 4: type_in_parentheses "void"
114 * line 4: rparen_or_rbracket ")"
115 * line 4: rparen_or_rbracket ")"
116 * line 4: newline "\n"
117 * line 5: lbrace "{"
118 * line 5: lbrace "{" repeated, see search_stmt
119 * line 5: newline "\n" FIXME: there is no newline in the source
120 * line 6: rbrace "}"
121 * line 6: eof "\n"
122 */
123 #indent input
124 void
125 t1 (char *a, int b,
126 void (*fn)(void))
127 {}
128 #indent end
129
130 #indent run
131 void
132 t1(char *a, int b,
133 void (*fn)(void))
134 {
135 }
136 #indent end
137
138
139 /* See opt_bc.c. */
140 #indent input
141 void t2 (char *x, int y)
142 {
143 int a,
144 b,
145 c;
146 int
147 *d,
148 *e,
149 *f;
150 int (*g)(),
151 (*h)(),
152 (*i)();
153 int j,
154 k,
155 l;
156 int m
157 ,n
158 ,o
159 ;
160 int chars[ /* push the comma beyond column 74 .... */ ], x;
161 }
162 #indent end
163
164 #indent run
165 void
166 t2(char *x, int y)
167 {
168 int a, b, c;
169 int
170 *d, *e, *f;
171 int (*g)(), (*h)(), (*i)();
172 int j, k, l;
173 int m
174 ,n
175 ,o
176 ;
177 int chars[ /* push the comma beyond column 74 .... */ ],
178 x;
179 }
180 #indent end
181
182
183 #indent input
184 const int int_minimum_size =
185 MAXALIGN(offsetof(int, test)) + MAXIMUM_ALIGNOF;
186 #indent end
187
188 #indent run-equals-input
189
190
191 /*
192 * Ensure that the usual GCC-style function attributes are formatted in a
193 * sensible way.
194 */
195 #indent input
196 void function(const char *, ...) __attribute__((format(printf, 1, 2)));
197 #indent end
198
199 /* FIXME: missing space before '__attribute__' */
200 #indent run -di0
201 void function(const char *, ...)__attribute__((format(printf, 1, 2)));
202 #indent end
203
204 /* FIXME: missing space before '__attribute__' */
205 #indent run
206 void function(const char *, ...)__attribute__((format(printf, 1, 2)));
207 #indent end
208
209
210 #indent input
211 static
212 _attribute_printf(1, 2)
213 void
214 print_error(const char *fmt,...)
215 {
216 }
217 #indent end
218
219 #indent run
220 static
221 _attribute_printf(1, 2)
222 void
223 print_error(const char *fmt, ...)
224 {
225 }
226 #indent end
227
228
229 #indent input
230 static _attribute_printf(1, 2)
231 void
232 print_error(const char *fmt,...)
233 {
234 }
235 #indent end
236
237 #indent run
238 static _attribute_printf(1, 2)
239 void
240 print_error(const char *fmt, ...)
241 {
242 }
243 #indent end
244
245
246 #indent input
247 static void _attribute_printf(1, 2)
248 print_error(const char *fmt,...)
249 {
250 }
251 #indent end
252
253 #indent run
254 static void
255 _attribute_printf(1, 2)
256 print_error(const char *fmt, ...)
257 {
258 }
259 #indent end
260
261
262 /* See FreeBSD r309380 */
263 #indent input
264 static LIST_HEAD(, alq) ald_active;
265 static int ald_shutting_down = 0;
266 struct thread *ald_thread;
267 #indent end
268
269 #indent run
270 static LIST_HEAD(, alq) ald_active;
271 static int ald_shutting_down = 0;
272 struct thread *ald_thread;
273 #indent end
274
275
276 #indent input
277 static int
278 old_style_definition(a, b, c)
279 struct thread *a;
280 int b;
281 double ***c;
282 {
283
284 }
285 #indent end
286
287 #indent run
288 static int
289 old_style_definition(a, b, c)
290 struct thread *a;
291 int b;
292 double ***c;
293 {
294
295 }
296 #indent end
297
298
299 /*
300 * Demonstrate how variable declarations are broken into several lines when
301 * the line length limit is set quite low.
302 */
303 #indent input
304 struct s a,b;
305 struct s0 a,b;
306 struct s01 a,b;
307 struct s012 a,b;
308 struct s0123 a,b;
309 struct s01234 a,b;
310 struct s012345 a,b;
311 struct s0123456 a,b;
312 struct s01234567 a,b;
313 struct s012345678 a,b;
314 struct s0123456789 a,b;
315 struct s01234567890 a,b;
316 struct s012345678901 a,b;
317 struct s0123456789012 a,b;
318 struct s01234567890123 a,b;
319 #indent end
320
321 #indent run -l20 -di0
322 struct s a, b;
323 /* $ XXX: See process_comma, varname_len for why this line is broken. */
324 struct s0 a,
325 b;
326 /* $ XXX: The indentation of the second line is wrong. The variable names */
327 /* $ XXX: 'a' and 'b' should be in the same column; the word 'struct' is */
328 /* $ XXX: missing in the calculation for the indentation. */
329 struct s01 a,
330 b;
331 struct s012 a,
332 b;
333 struct s0123 a,
334 b;
335 struct s01234 a,
336 b;
337 struct s012345 a,
338 b;
339 struct s0123456 a,
340 b;
341 struct s01234567 a,
342 b;
343 struct s012345678 a,
344 b;
345 struct s0123456789 a,
346 b;
347 struct s01234567890 a,
348 b;
349 struct s012345678901 a,
350 b;
351 struct s0123456789012 a,
352 b;
353 struct s01234567890123 a,
354 b;
355 #indent end
356
357
358 #indent input
359 char * x(void)
360 {
361 type identifier;
362 type *pointer;
363 unused * value;
364 (void)unused * value;
365
366 dmax = (double)3 * 10.0;
367 dmin = (double)dmax * 10.0;
368 davg = (double)dmax * dmin;
369
370 return NULL;
371 }
372 #indent end
373
374 #indent run
375 char *
376 x(void)
377 {
378 type identifier;
379 type *pointer;
380 unused *value;
381 (void)unused * value;
382
383 dmax = (double)3 * 10.0;
384 dmin = (double)dmax * 10.0;
385 davg = (double)dmax * dmin;
386
387 return NULL;
388 }
389 #indent end
390
391
392 #indent input
393 int *
394 y(void) {
395
396 }
397
398 int
399 z(void) {
400
401 }
402 #indent end
403
404 #indent run
405 int *
406 y(void)
407 {
408
409 }
410
411 int
412 z(void)
413 {
414
415 }
416 #indent end
417
418
419 #indent input
420 int x;
421 int *y;
422 int * * * * z;
423 #indent end
424
425 #indent run
426 int x;
427 int *y;
428 int ****z;
429 #indent end
430
431
432 #indent input
433 int main(void) {
434 char (*f1)() = NULL;
435 char *(*f1)() = NULL;
436 char *(*f2)();
437 }
438 #indent end
439
440 /*
441 * Before NetBSD io.c 1.103 from 2021-10-27, indent wrongly placed the second
442 * and third variable declaration in column 1. This bug has been introduced
443 * to NetBSD when FreeBSD indent was imported in 2019.
444 */
445 #indent run -ldi0
446 int
447 main(void)
448 {
449 char (*f1)() = NULL;
450 char *(*f1)() = NULL;
451 char *(*f2)();
452 }
453 #indent end
454
455 #indent run
456 int
457 main(void)
458 {
459 /* $ XXX: Not really pretty, the name 'f1' should be aligned, if at all. */
460 char (*f1)() = NULL;
461 /* $ XXX: Not really pretty, the name 'f1' should be aligned, if at all. */
462 char *(* f1)() = NULL;
463 /* $ XXX: Not really pretty, the name 'f2' should be aligned, if at all. */
464 char *(* f2)();
465 }
466 #indent end
467
468
469 /*
470 * In some ancient time long before ISO C90, variable declarations with
471 * initializer could be written without '='. The C Programming Language from
472 * 1978 doesn't mention this form anymore.
473 *
474 * Before NetBSD lexi.c 1.123 from 2021-10-31, indent treated the '-' as a
475 * unary operator.
476 */
477 #indent input
478 int a - 1;
479 {
480 int a - 1;
481 }
482 #indent end
483
484 #indent run -di0
485 int a - 1;
486 {
487 int a - 1;
488 }
489 #indent end
490
491
492 /*
493 * Between 2019-04-04 and before lexi.c 1.146 from 2021-11-19, the indentation
494 * of the '*' depended on the function name, which did not make sense. For
495 * function names that matched [A-Za-z]+, the '*' was placed correctly, for
496 * all other function names (containing [$0-9_]) the '*' was right-aligned on
497 * the declaration indentation, which defaults to 16.
498 */
499 #indent input
500 int *
501 f2(void)
502 {
503 }
504
505 int *
506 yy(void)
507 {
508 }
509
510 int *
511 int_create(void)
512 {
513 }
514 #indent end
515
516 #indent run-equals-input
517
518
519 /*
520 * Since 2019-04-04, the space between the '){' is missing.
521 */
522 #indent input
523 int *
524 function_name_____20________30________40________50
525 (void)
526 {}
527 #indent end
528
529 /* FIXME: The space between '){' is missing. */
530 #indent run
531 int *function_name_____20________30________40________50
532 (void){
533 }
534 #indent end
535
536
537 /*
538 * Since 2019-04-04 and before lexi.c 1.144 from 2021-11-19, some function
539 * names were preserved while others were silently discarded.
540 */
541 #indent input
542 int *
543 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
544 (void)
545 {}
546 #indent end
547
548 #indent run
549 int *aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
550 (void){
551 }
552 #indent end
553
554
555 /*
556 * Before 1990, when C90 standardized function prototypes, a function
557 * declaration or definition did not contain a '*' that may have looked
558 * similar to the binary operator '*' because it was surrounded by two
559 * identifiers.
560 *
561 * As of 2021-11-21, indent interprets the '*' in the function declaration in
562 * line 1 as a binary operator, even though it is followed by a ',' directly.
563 * In the function declaration in line 2, as well as the function definition
564 * in line 4, indent interprets the '*' as a binary operator as well, which
565 * kind of makes sense since it is surrounded by words, but it's still in a
566 * declaration.
567 *
568 * Essentially, as of 2021, indent has missed the last 31 years of advances in
569 * the C programming language. Instead, the workaround has been to pass all
570 * type names via the options '-ta' and '-T'.
571 */
572 #indent input
573 void buffer_add(buffer *, char);
574 void buffer_add(buffer *buf, char ch);
575
576 void
577 buffer_add(buffer *buf, char ch)
578 {
579 *buf->e++ = ch;
580 }
581 #indent end
582
583 #indent run
584 void buffer_add(buffer *, char);
585 void buffer_add(buffer * buf, char ch);
586
587 void
588 buffer_add(buffer * buf, char ch)
589 {
590 *buf->e++ = ch;
591 }
592 #indent end
593
594
595 /*
596 * Indent gets easily confused by type names it does not know about.
597 */
598 #indent input
599 static Token
600 ToToken(bool cond)
601 {
602 }
603 #indent end
604
605 #indent run-equals-input -TToken
606 /* Since lexi.c 1.153 from 2021-11-25. */
607 #indent run-equals-input
608
609
610 /*
611 * Indent gets easily confused by unknown type names in struct declarations.
612 */
613 #indent input
614 typedef struct OpenDirs {
615 CachedDirList list;
616 HashTable /* of CachedDirListNode */ table;
617 } OpenDirs;
618 #indent end
619
620 /* FIXME: The word 'HashTable' must not be aligned like a member name. */
621 #indent run
622 typedef struct OpenDirs {
623 CachedDirList list;
624 HashTable /* of CachedDirListNode */ table;
625 } OpenDirs;
626 #indent end
627
628 #indent run-equals-input -THashTable
629
630
631 /*
632 * Indent gets easily confused by unknown type names, even in declarations
633 * that are syntactically unambiguous.
634 */
635 #indent input
636 static CachedDir *dot = NULL;
637 #indent end
638
639 #indent run-equals-input -TCachedDir
640 /* Since lexi.c 1.153 from 2021-11-25. */
641 #indent run-equals-input
642
643
644 /*
645 * Indent gets easily confused by unknown type names in declarations.
646 */
647 #indent input
648 static CachedDir *
649 CachedDir_New(const char *name)
650 {
651 }
652 #indent end
653
654 /* Since lexi.c 1.153 from 2021-11-25. */
655 #indent run-equals-input
656
657
658 /*
659 * Indent gets easily confused by unknown type names in function declarations.
660 */
661 #indent input
662 static CachedDir *
663 CachedDir_Ref(CachedDir *dir)
664 {
665 }
666 #indent end
667
668 /* FIXME: Extraneous ' ' between '*' and 'dir'. */
669 #indent run
670 static CachedDir *
671 CachedDir_Ref(CachedDir * dir)
672 {
673 }
674 #indent end
675
676
677 /*
678 * In some cases, indent does not get confused by unknown type names. At least
679 * it gets the placement of the '{' correct in this example.
680 */
681 #indent input
682 static bool
683 HashEntry_KeyEquals(const HashEntry *he, Substring key)
684 {
685 }
686 #indent end
687
688 #indent run
689 static bool
690 HashEntry_KeyEquals(const HashEntry * he, Substring key)
691 {
692 }
693 #indent end
694
695
696 /*
697 * Indent doesn't notice that the two '*' are in a declaration, instead it
698 * interprets the first '*' as a binary operator.
699 */
700 #indent input
701 static void
702 CachedDir_Assign(CachedDir **var, CachedDir *dir)
703 {
704 }
705 #indent end
706
707 /* FIXME: Extraneous space between '*' and '*'. */
708 #indent run
709 static void
710 CachedDir_Assign(CachedDir * *var, CachedDir * dir)
711 {
712 }
713 #indent end
714
715 #indent run-equals-input -TCachedDir
716
717
718 /*
719 * Before lexi.c 1.153 from 2021-11-25, all initializer expressions after the
720 * first one were indented as if they would be statement continuations. This
721 * was because the token 'Shell' was identified as a word, not as a type name.
722 */
723 #indent input
724 static Shell shells[] = {
725 {
726 first,
727 second,
728 },
729 };
730 #indent end
731
732 /* Since lexi.c 1.153 from 2021-11-25. */
733 #indent run-equals-input
734
735
736 /*
737 * Indent gets easily confused by function attribute macros that follow the
738 * function declaration.
739 */
740 #indent input
741 static void JobInterrupt(bool, int) MAKE_ATTR_DEAD;
742 static void JobRestartJobs(void);
743 #indent end
744
745 #indent run
746 /* $ FIXME: This is a declaration, not a definition, thus no line break before the name. */
747 /* $ FIXME: Missing space before 'MAKE_ATTR_DEAD'. */
748 static void
749 JobInterrupt(bool, int)MAKE_ATTR_DEAD;
750 /* $ FIXME: Must not be indented. */
751 static void JobRestartJobs(void);
752 #indent end
753
754
755 /*
756 * Indent gets easily confused by function modifier macros.
757 */
758 #indent input
759 MAKE_INLINE const char *
760 GNode_VarTarget(GNode *gn) { return GNode_ValueDirect(gn, TARGET); }
761 #indent end
762
763 /* FIXME: The function name must be in column 1 of a separate line. */
764 /* FIXME: The '{' must be in column 1 of the next line. */
765 /* FIXME: The '*' before 'gn' is extraneous. */
766 /* FIXME: The indentation depends on the function body; try 'return 0'. */
767 #indent run
768 MAKE_INLINE const char *GNode_VarTarget(GNode * gn) {
769 return GNode_ValueDirect(gn, TARGET);
770 }
771 #indent end
772
773 /* FIXME: Missing space between '*' and 'gn'. */
774 #indent run -TGNode
775 MAKE_INLINE const char *GNode_VarTarget(GNode *gn){
776 return GNode_ValueDirect(gn, TARGET);
777 }
778 #indent end
779
780
781 /*
782 * Ensure that '*' in declarations is interpreted (or at least formatted) as
783 * a 'pointer to' type derivation, not as a binary or unary operator.
784 */
785 #indent input
786 number *var = a * b;
787
788 void
789 function(void)
790 {
791 number *var = a * b;
792 }
793 #indent end
794
795 #indent run-equals-input -di0
796