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