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
sigpipe(int sig)58 sigpipe(int sig)
59 {
60 }
61
62 static struct block *
alloc_block(void)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
write_block(int fd,block_head_t * ph)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
peek_block(block_head_t * pbh,uint64_t off)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
set_block(block_head_t * pbh,uint64_t off,uint16_t ch)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
size_block(block_head_t * pbh)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
diff_tool(block_head_t * pa,block_head_t * pb)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
diff_block(block_head_t * pa,block_head_t * pb)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
free_block(block_head_t * pbh)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
cmd_popen(char * command,FILE ** iop)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
cmd_block_process(block_head_t * pbh_in,block_head_t * pbh_out,char * cmd_str)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
usage(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
main(int argc,char ** argv)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 }
745