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