]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/indent_wrapper/indent_wrapper.c
Add 'contrib/unifdef/' from commit '0da44885831dc0a43c4ca6ff04a2430993cc0a80'
[FreeBSD/FreeBSD.git] / tools / tools / indent_wrapper / indent_wrapper.c
1 /*-
2  * Copyright (c) 2015 Hans Petter Selasky. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <sys/queue.h>
29 #include <sysexits.h>
30 #include <err.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <signal.h>
37
38 extern char **environ;
39
40 static int opt_verbose;
41 static char *opt_diff_tool;
42
43 #define BLOCK_SIZE      4096
44 #define BLOCK_MASK      0x100
45 #define BLOCK_ADD       0x200
46
47 struct block {
48         TAILQ_ENTRY(block) entry;
49         uint32_t length;
50         uint32_t flags;
51         uint8_t *data;
52         uint8_t *mask;
53 };
54
55 typedef TAILQ_HEAD(, block) block_head_t;
56
57 static void
58 sigpipe(int sig)
59 {
60 }
61
62 static struct block *
63 alloc_block(void)
64 {
65         struct block *pb;
66         size_t size = sizeof(*pb) + (2 * BLOCK_SIZE);
67
68         pb = malloc(size);
69         if (pb == NULL)
70                 errx(EX_SOFTWARE, "Out of memory");
71         memset(pb, 0, size);
72         pb->data = (void *)(pb + 1);
73         pb->mask = pb->data + BLOCK_SIZE;
74         pb->length = BLOCK_SIZE;
75         return (pb);
76 }
77
78 static int
79 write_block(int fd, block_head_t *ph)
80 {
81         struct block *ptr;
82
83         if (fd < 0)
84                 return (-1);
85
86         TAILQ_FOREACH(ptr, ph, entry) {
87                 if (write(fd, ptr->data, ptr->length) != ptr->length)
88                         return (-1);
89         }
90         return (0);
91 }
92
93 static uint16_t
94 peek_block(block_head_t *pbh, uint64_t off)
95 {
96         struct block *ptr;
97
98         TAILQ_FOREACH(ptr, pbh, entry) {
99                 if (off < ptr->length)
100                         break;
101                 off -= ptr->length;
102         }
103         if (ptr == NULL)
104                 return (0);
105         return (ptr->data[off] | (ptr->mask[off] << 8));
106 }
107
108 static void
109 set_block(block_head_t *pbh, uint64_t off, uint16_t ch)
110 {
111         struct block *ptr;
112
113         TAILQ_FOREACH(ptr, pbh, entry) {
114                 if (off < ptr->length)
115                         break;
116                 off -= ptr->length;
117         }
118         if (ptr == NULL)
119                 return;
120         ptr->data[off] = ch & 0xFF;
121         ptr->mask[off] = (ch >> 8) & 0xFF;
122 }
123
124 static uint64_t
125 size_block(block_head_t *pbh)
126 {
127         struct block *ptr;
128         uint64_t off = 0;
129
130         TAILQ_FOREACH(ptr, pbh, entry)
131             off += ptr->length;
132         return (off);
133 }
134
135 static int
136 diff_tool(block_head_t *pa, block_head_t *pb)
137 {
138         char ca[] = {"/tmp/diff.orig.XXXXXX"};
139         char cb[] = {"/tmp/diff.styled.XXXXXX"};
140         char cc[256];
141         uint64_t sa;
142         uint64_t sb;
143         uint64_t s;
144         uint64_t x;
145         int fa;
146         int fb;
147
148         sa = size_block(pa);
149         sb = size_block(pb);
150         s = (sa > sb) ? sa : sb;
151
152         for (x = 0; x != s; x++) {
153                 char cha = peek_block(pa, x) & 0xFF;
154                 char chb = peek_block(pb, x) & 0xFF;
155
156                 if (cha != chb) {
157                         /* false positive */
158                         if (cha == '\n' && chb == 0 && x == sa - 1)
159                                 return (0);
160                         break;
161                 }
162         }
163         if (x == s)
164                 return (0);             /* identical */
165
166         fa = mkstemp(ca);
167         fb = mkstemp(cb);
168
169         if (write_block(fa, pa) < 0 || write_block(fb, pb) < 0) {
170                 close(fa);
171                 close(fb);
172                 unlink(ca);
173                 unlink(cb);
174                 err(EX_SOFTWARE, "Could not write data to temporary files");
175         }
176         close(fa);
177         close(fb);
178
179         snprintf(cc, sizeof(cc), "%s %s %s", opt_diff_tool, ca, cb);
180         system(cc);
181
182         unlink(ca);
183         unlink(cb);
184         return (-1);
185 }
186
187 static int
188 diff_block(block_head_t *pa, block_head_t *pb)
189 {
190         uint64_t sa = size_block(pa);
191         uint64_t sb = size_block(pb);
192         uint64_t s;
193         uint64_t x;
194         uint64_t y;
195         uint64_t n;
196
197         s = (sa > sb) ? sa : sb;
198
199         for (y = x = 0; x != s; x++) {
200                 char cha = peek_block(pa, x) & 0xFF;
201                 char chb = peek_block(pb, x) & 0xFF;
202
203                 if (cha != chb) {
204                         int nonspace;
205
206                         /* false positive */
207                         if (cha == '\n' && chb == 0 && x == sa - 1)
208                                 return (0);
209
210                         n = x - y;
211                         printf("Style error:\n");
212                         nonspace = 0;
213                         for (n = y; n < sa; n++) {
214                                 char ch = peek_block(pa, n) & 0xFF;
215
216                                 if (nonspace && ch == '\n')
217                                         break;
218                                 printf("%c", ch);
219                                 if (!isspace(ch))
220                                         nonspace = 1;
221                         }
222                         printf("\n");
223                         printf("Style corrected:\n");
224                         nonspace = 0;
225                         for (n = y; n < sb; n++) {
226                                 char ch = peek_block(pb, n) & 0xFF;
227
228                                 if (nonspace && ch == '\n')
229                                         break;
230                                 printf("%c", ch);
231                                 if (!isspace(ch))
232                                         nonspace = 1;
233                         }
234                         printf("\n");
235                         for (n = y; n != x; n++) {
236                                 if ((peek_block(pa, n) & 0xFF) == '\t')
237                                         printf("\t");
238                                 else
239                                         printf(" ");
240                         }
241                         printf("^ %sdifference%s\n",
242                             (isspace(cha) || isspace(chb)) ? "whitespace " : "",
243                             (x >= sa || x >= sb) ? " in the end of a block" : "");
244                         return (1);
245                 } else if (cha == '\n') {
246                         y = x + 1;
247                 }
248         }
249         return (0);
250 }
251
252 static void
253 free_block(block_head_t *pbh)
254 {
255         struct block *ptr;
256
257         while ((ptr = TAILQ_FIRST(pbh))) {
258                 TAILQ_REMOVE(pbh, ptr, entry);
259                 free(ptr);
260         }
261 }
262
263 static void
264 cmd_popen(char *command, FILE **iop)
265 {
266         char *argv[4];
267         int pdes[4];
268         int pid;
269
270         if (pipe(pdes) < 0)
271                 goto error;
272
273         if (pipe(pdes + 2) < 0) {
274                 close(pdes[0]);
275                 close(pdes[1]);
276                 goto error;
277         }
278         argv[0] = "sh";
279         argv[1] = "-c";
280         argv[2] = command;
281         argv[3] = NULL;
282
283         switch ((pid = vfork())) {
284         case -1:                        /* Error. */
285                 close(pdes[0]);
286                 close(pdes[1]);
287                 close(pdes[2]);
288                 close(pdes[3]);
289                 goto error;
290         case 0:                 /* Child. */
291                 dup2(pdes[1], STDOUT_FILENO);
292                 dup2(pdes[2], STDIN_FILENO);
293                 close(pdes[0]);
294                 close(pdes[3]);
295                 execve("/bin/sh", argv, environ);
296                 exit(127);
297         default:
298                 break;
299         }
300         iop[0] = fdopen(pdes[3], "w");
301         iop[1] = fdopen(pdes[0], "r");
302         close(pdes[1]);
303         close(pdes[2]);
304         return;
305 error:
306         iop[0] = iop[1] = NULL;
307 }
308
309 static void
310 cmd_block_process(block_head_t *pbh_in, block_head_t *pbh_out, char *cmd_str)
311 {
312         FILE *pfd[2];
313         struct block *ptr;
314
315         TAILQ_INIT(pbh_out);
316
317         cmd_popen(cmd_str, pfd);
318
319         if (pfd[0] == NULL || pfd[1] == NULL)
320                 errx(EX_SOFTWARE, "Cannot invoke command '%s'", cmd_str);
321
322         if (pbh_in != NULL) {
323                 TAILQ_FOREACH(ptr, pbh_in, entry) {
324                         if (fwrite(ptr->data, 1, ptr->length, pfd[0]) != ptr->length)
325                                 err(EX_SOFTWARE, "Cannot write all data to command '%s'", cmd_str);
326                 }
327                 fflush(pfd[0]);
328         }
329         fclose(pfd[0]);
330
331         while (1) {
332                 int len;
333
334                 ptr = alloc_block();
335                 len = fread(ptr->data, 1, BLOCK_SIZE, pfd[1]);
336                 if (len <= 0) {
337                         free(ptr);
338                         break;
339                 }
340                 ptr->length = len;
341                 TAILQ_INSERT_TAIL(pbh_out, ptr, entry);
342         }
343         fclose(pfd[1]);
344 }
345
346 static void
347 usage(void)
348 {
349         fprintf(stderr,
350             "indent_wrapper [-v] [-d] [-D] [-g <githash>]\n"
351             "\t" "[-s <svnrevision> ] [ -t <tool> ] [ -c <command> ]\n"
352             "\t" "-v        Increase verbosity\n"
353             "\t" "-d        Check output from git diff\n"
354             "\t" "-D        Check output from svn diff\n"
355             "\t" "-c <cmd>  Set custom command to produce diff\n"
356             "\t" "-g <hash> Check output from git hash\n"
357             "\t" "-s <rev>  Check output from svn revision\n"
358             "\t" "-t <tool> Launch external diff tool\n"
359             "\n"
360             "Examples:\n"
361             "\t" "indent_wrapper -D\n"
362             "\t" "indent_wrapper -D -t meld\n"
363             "\t" "indent_wrapper -D -t \"diff -u\"\n");
364         exit(EX_SOFTWARE);
365 }
366
367 int
368 main(int argc, char **argv)
369 {
370         block_head_t diff_head;
371         block_head_t diff_a_head;
372         block_head_t diff_b_head;
373         block_head_t indent_in_head;
374         block_head_t indent_out_head;
375         struct block *p1 = NULL;
376         struct block *p2 = NULL;
377         uint64_t size;
378         uint64_t x;
379         uint64_t y1 = 0;
380         uint64_t y2 = 0;
381         int recurse = 0;
382         int inside_string = 0;
383         int escape_char = 0;
384         int do_parse = 0;
385         char cmdbuf[256];
386         uint16_t ch;
387         uint16_t chn;
388         int c;
389         int retval = 0;
390
391         signal(SIGPIPE, &sigpipe);
392
393         cmdbuf[0] = 0;
394
395         while ((c = getopt(argc, argv, "dDvg:s:c:ht:")) != -1) {
396                 switch (c) {
397                 case 'v':
398                         opt_verbose++;
399                         break;
400                 case 't':
401                         opt_diff_tool = optarg;
402                         break;
403                 case 'g':
404                         snprintf(cmdbuf, sizeof(cmdbuf), "git show -U1000000 %s", optarg);
405                         break;
406                 case 'd':
407                         snprintf(cmdbuf, sizeof(cmdbuf), "git diff -U1000000");
408                         break;
409                 case 'D':
410                         snprintf(cmdbuf, sizeof(cmdbuf), "svn diff --diff-cmd=diff -x -U1000000");
411                         break;
412                 case 's':
413                         snprintf(cmdbuf, sizeof(cmdbuf), "svn diff --diff-cmd=diff -x -U1000000 -r %s", optarg);
414                         break;
415                 case 'c':
416                         snprintf(cmdbuf, sizeof(cmdbuf), "%s", optarg);
417                         break;
418                 default:
419                         usage();
420                 }
421         }
422         if (cmdbuf[0] == 0)
423                 usage();
424
425         cmd_block_process(NULL, &diff_head, cmdbuf);
426
427         TAILQ_INIT(&diff_a_head);
428         TAILQ_INIT(&diff_b_head);
429
430         size = size_block(&diff_head);
431         p1 = alloc_block();
432         y1 = 0;
433         p2 = alloc_block();
434         y2 = 0;
435
436         for (x = 0; x < size;) {
437                 ch = peek_block(&diff_head, x);
438                 switch (ch & 0xFF) {
439                 case '+':
440                         if (ch == peek_block(&diff_head, x + 1) &&
441                             ch == peek_block(&diff_head, x + 2) &&
442                             ' ' == (peek_block(&diff_head, x + 3) & 0xFF))
443                                 goto parse_filename;
444                         if (do_parse == 0)
445                                 break;
446                         for (x++; x != size; x++) {
447                                 ch = peek_block(&diff_head, x);
448                                 p1->mask[y1] = BLOCK_ADD >> 8;
449                                 p1->data[y1++] = ch;
450                                 if (y1 == BLOCK_SIZE) {
451                                         TAILQ_INSERT_TAIL(&diff_a_head, p1, entry);
452                                         p1 = alloc_block();
453                                         y1 = 0;
454                                 }
455                                 if ((ch & 0xFF) == '\n')
456                                         break;
457                         }
458                         break;
459                 case '-':
460                         if (ch == peek_block(&diff_head, x + 1) &&
461                             ch == peek_block(&diff_head, x + 2) &&
462                             ' ' == (peek_block(&diff_head, x + 3) & 0xFF))
463                                 goto parse_filename;
464                         if (do_parse == 0)
465                                 break;
466                         for (x++; x != size; x++) {
467                                 ch = peek_block(&diff_head, x);
468                                 p2->data[y2++] = ch;
469                                 if (y2 == BLOCK_SIZE) {
470                                         TAILQ_INSERT_TAIL(&diff_b_head, p2, entry);
471                                         p2 = alloc_block();
472                                         y2 = 0;
473                                 }
474                                 if ((ch & 0xFF) == '\n')
475                                         break;
476                         }
477                         break;
478                 case ' ':
479                         if (do_parse == 0)
480                                 break;
481                         for (x++; x != size; x++) {
482                                 ch = peek_block(&diff_head, x);
483                                 p1->data[y1++] = ch;
484                                 if (y1 == BLOCK_SIZE) {
485                                         TAILQ_INSERT_TAIL(&diff_a_head, p1, entry);
486                                         p1 = alloc_block();
487                                         y1 = 0;
488                                 }
489                                 p2->data[y2++] = ch;
490                                 if (y2 == BLOCK_SIZE) {
491                                         TAILQ_INSERT_TAIL(&diff_b_head, p2, entry);
492                                         p2 = alloc_block();
493                                         y2 = 0;
494                                 }
495                                 if ((ch & 0xFF) == '\n')
496                                         break;
497                         }
498                         break;
499         parse_filename:
500                         for (x += 3; x != size; x++) {
501                                 ch = peek_block(&diff_head, x);
502                                 chn = peek_block(&diff_head, x + 1);
503                                 if ((ch & 0xFF) == '.') {
504                                         /* only accept .c and .h files */
505                                         do_parse = ((chn & 0xFF) == 'c' || (chn & 0xFF) == 'h');
506                                 }
507                                 if ((ch & 0xFF) == '\n')
508                                         break;
509                         }
510                 default:
511                         break;
512                 }
513                 /* skip till end of line */
514                 for (; x < size; x++) {
515                         ch = peek_block(&diff_head, x);
516                         if ((ch & 0xFF) == '\n') {
517                                 x++;
518                                 break;
519                         }
520                 }
521         }
522         p1->length = y1;
523         p2->length = y2;
524         TAILQ_INSERT_TAIL(&diff_a_head, p1, entry);
525         TAILQ_INSERT_TAIL(&diff_b_head, p2, entry);
526
527         /* first pass - verify input */
528         size = size_block(&diff_a_head);
529         for (x = 0; x != size; x++) {
530                 ch = peek_block(&diff_a_head, x) & 0xFF;
531                 if (!(ch & 0x80) && ch != '\t' && ch != '\r' && ch != '\n' &&
532                     ch != ' ' && !isprint(ch))
533                         errx(EX_SOFTWARE, "Non printable characters are not allowed: '%c'", ch);
534                 else if (ch & 0x80) {
535                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
536                 }
537         }
538
539         /* second pass - identify all comments */
540         for (x = 0; x < size; x++) {
541                 ch = peek_block(&diff_a_head, x);
542                 chn = peek_block(&diff_a_head, x + 1);
543                 if ((ch & 0xFF) == '/' && (chn & 0xFF) == '/') {
544                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
545                         set_block(&diff_a_head, x + 1, chn | BLOCK_MASK);
546                         for (x += 2; x < size; x++) {
547                                 ch = peek_block(&diff_a_head, x);
548                                 if ((ch & 0xFF) == '\n')
549                                         break;
550                                 set_block(&diff_a_head, x, ch | BLOCK_MASK);
551                         }
552                 } else if ((ch & 0xFF) == '/' && (chn & 0xFF) == '*') {
553                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
554                         set_block(&diff_a_head, x + 1, chn | BLOCK_MASK);
555                         for (x += 2; x < size; x++) {
556                                 ch = peek_block(&diff_a_head, x);
557                                 chn = peek_block(&diff_a_head, x + 1);
558                                 if ((ch & 0xFF) == '*' && (chn & 0xFF) == '/') {
559                                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
560                                         set_block(&diff_a_head, x + 1, chn | BLOCK_MASK);
561                                         x++;
562                                         break;
563                                 }
564                                 set_block(&diff_a_head, x, ch | BLOCK_MASK);
565                         }
566                 }
567         }
568
569         /* third pass - identify preprocessor tokens and strings */
570         for (x = 0; x < size; x++) {
571                 ch = peek_block(&diff_a_head, x);
572                 if (ch & BLOCK_MASK)
573                         continue;
574                 if (inside_string == 0 && (ch & 0xFF) == '#') {
575                         int skip_newline = 0;
576
577                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
578                         for (x++; x < size; x++) {
579                                 ch = peek_block(&diff_a_head, x);
580                                 if ((ch & 0xFF) == '\n') {
581                                         if (!skip_newline)
582                                                 break;
583                                         skip_newline = 0;
584                                 }
585                                 if (ch & BLOCK_MASK)
586                                         continue;
587                                 if ((ch & 0xFF) == '\\')
588                                         skip_newline = 1;
589                                 set_block(&diff_a_head, x, ch | BLOCK_MASK);
590                         }
591                 }
592                 if ((ch & 0xFF) == '"' || (ch & 0xFF) == '\'') {
593                         if (inside_string == 0) {
594                                 inside_string = (ch & 0xFF);
595                         } else {
596                                 if (escape_char == 0 && inside_string == (ch & 0xFF))
597                                         inside_string = 0;
598                         }
599                         escape_char = 0;
600                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
601                 } else if (inside_string != 0) {
602                         if ((ch & 0xFF) == '\\')
603                                 escape_char = !escape_char;
604                         else
605                                 escape_char = 0;
606                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
607                 }
608         }
609
610         /* fourth pass - identify function blocks */
611         if (opt_verbose > 0) {
612                 chn = peek_block(&diff_a_head, x);
613                 printf("L%02d%c|", recurse,
614                     (chn & BLOCK_ADD) ? '+' : ' ');
615         }
616         for (x = 0; x < size; x++) {
617                 ch = peek_block(&diff_a_head, x);
618                 if (opt_verbose > 0) {
619                         printf("%c", ch & 0xFF);
620                         if ((ch & 0xFF) == '\n') {
621                                 chn = peek_block(&diff_a_head, x + 1);
622                                 printf("L%02d%c|", recurse,
623                                     (chn & BLOCK_ADD) ? '+' : ' ');
624                         }
625                 }
626                 if (ch & BLOCK_MASK)
627                         continue;
628                 switch (ch & 0xFF) {
629                 case '{':
630                 case '(':
631                         recurse++;
632                         break;
633                 default:
634                         break;
635                 }
636                 if (recurse != 0)
637                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
638                 switch (ch & 0xFF) {
639                 case '}':
640                 case ')':
641                         recurse--;
642                         break;
643                 default:
644                         break;
645                 }
646         }
647         if (opt_verbose > 0)
648                 printf("\n");
649         if (recurse != 0)
650                 errx(EX_SOFTWARE, "Unbalanced parenthesis");
651         if (inside_string != 0)
652                 errx(EX_SOFTWARE, "String without end");
653
654         /* fifth pass - on the same line statements */
655         for (x = 0; x < size; x++) {
656                 ch = peek_block(&diff_a_head, x);
657                 if (ch & BLOCK_MASK)
658                         continue;
659                 switch (ch & 0xFF) {
660                 case '\n':
661                         break;
662                 default:
663                         set_block(&diff_a_head, x, ch | BLOCK_MASK);
664                         break;
665                 }
666         }
667
668         /* sixth pass - output relevant blocks to indent */
669         for (y1 = x = 0; x < size; x++) {
670                 ch = peek_block(&diff_a_head, x);
671                 if (ch & BLOCK_ADD) {
672                         TAILQ_INIT(&indent_in_head);
673
674                         p2 = alloc_block();
675                         y2 = 0;
676                         for (; y1 < size; y1++) {
677                                 ch = peek_block(&diff_a_head, y1);
678                                 if (y1 > x && !(ch & (BLOCK_MASK | BLOCK_ADD)))
679                                         break;
680                                 p2->data[y2++] = ch & 0xFF;
681                                 if (y2 == BLOCK_SIZE) {
682                                         TAILQ_INSERT_TAIL(&indent_in_head, p2, entry);
683                                         p2 = alloc_block();
684                                         y2 = 0;
685                                 }
686                         }
687                         if (p2->data[y2] != '\n')
688                                 p2->data[y2++] = '\n';
689                         p2->length = y2;
690                         TAILQ_INSERT_TAIL(&indent_in_head, p2, entry);
691
692                         cmd_block_process(&indent_in_head, &indent_out_head,
693                             "indent "
694                             "-Tbool "
695                             "-Tclass "
696                             "-TFILE "
697                             "-TLIST_ENTRY "
698                             "-TLIST_HEAD "
699                             "-TSLIST_ENTRY "
700                             "-TSLIST_HEAD "
701                             "-TSTAILQ_ENTRY "
702                             "-TSTAILQ_HEAD "
703                             "-TTAILQ_ENTRY "
704                             "-TTAILQ_HEAD "
705                             "-T__aligned "
706                             "-T__packed "
707                             "-T__unused "
708                             "-T__used "
709                             "-Tfd_set "
710                             "-Toss_mixerinfo "
711                             "-Tu_char "
712                             "-Tu_int "
713                             "-Tu_long "
714                             "-Tu_short "
715                             "-ta -st -bad -bap -nbbb -nbc -br -nbs "
716                             "-c41 -cd41 -cdb -ce -ci4 -cli0 -d0 -di8 -ndj -ei -nfc1 "
717                             "-nfcb -i8 -ip8 -l79 -lc77 -ldi0 -nlp -npcs -psl -sc "
718                             "-nsob -nv "
719                             " | "
720                             "sed "
721                             "-e 's/_HEAD [(]/_HEAD(/g' "
722                             "-e 's/_ENTRY [(]/_ENTRY(/g' "
723                             "-e 's/\t__aligned/ __aligned/g' "
724                             "-e 's/\t__packed/ __packed/g' "
725                             "-e 's/\t__unused/ __unused/g' "
726                             "-e 's/\t__used/ __used/g' "
727                             "-e 's/^#define /#define\t/g'");
728
729                         if (opt_diff_tool != NULL) {
730                                 if (diff_tool(&indent_in_head, &indent_out_head))
731                                         retval = 1;
732                         } else {
733                                 if (diff_block(&indent_in_head, &indent_out_head))
734                                         retval = 1;
735                         }
736                         free_block(&indent_in_head);
737                         free_block(&indent_out_head);
738                         x = y1;
739                 } else if (!(ch & BLOCK_MASK)) {
740                         y1 = x + 1;
741                 }
742         }
743         return (retval);
744 }