source: trunk/minix/commands/patch/patch.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 19.4 KB
Line 
1char rcsid[] =
2 "$Header: /cvsup/minix/src/commands/patch/patch.c,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $";
3
4/* patch - a program to apply diffs to original files
5 *
6 * Copyright 1986, Larry Wall
7 *
8 * This program may be copied as long as you don't try to make any
9 * money off of it, or pretend that you wrote it.
10 *
11 * $Log: patch.c,v $
12 * Revision 1.1.1.1 2005/04/21 14:55:10 beng
13 * Initial import of pre-3.0.1
14 *
15 * Revision 1.1.1.1 2005/04/20 13:33:19 beng
16 * Initial import of minix 2.0.4
17 *
18 * Revision 2.0.1.6 88/06/22 20:46:39 lwall
19 * patch12: rindex() wasn't declared
20 *
21 * Revision 2.0.1.5 88/06/03 15:09:37 lwall
22 * patch10: exit code improved.
23 * patch10: better support for non-flexfilenames.
24 *
25 * Revision 2.0.1.4 87/02/16 14:00:04 lwall
26 * Short replacement caused spurious "Out of sync" message.
27 *
28 * Revision 2.0.1.3 87/01/30 22:45:50 lwall
29 * Improved diagnostic on sync error.
30 * Moved do_ed_script() to pch.c.
31 *
32 * Revision 2.0.1.2 86/11/21 09:39:15 lwall
33 * Fuzz factor caused offset of installed lines.
34 *
35 * Revision 2.0.1.1 86/10/29 13:10:22 lwall
36 * Backwards search could terminate prematurely.
37 *
38 * Revision 2.0 86/09/17 15:37:32 lwall
39 * Baseline for netwide release.
40 *
41 * Revision 1.5 86/08/01 20:53:24 lwall
42 * Changed some %d's to %ld's.
43 * Linted.
44 *
45 * Revision 1.4 86/08/01 19:17:29 lwall
46 * Fixes for machines that can't vararg.
47 * Added fuzz factor.
48 * Generalized -p.
49 * General cleanup.
50 *
51 * 85/08/15 van%ucbmonet@berkeley
52 * Changes for 4.3bsd diff -c.
53 *
54 * Revision 1.3 85/03/26 15:07:43 lwall
55 * Frozen.
56 *
57 * Revision 1.2.1.9 85/03/12 17:03:35 lwall
58 * Changed pfp->_file to fileno(pfp).
59 *
60 * Revision 1.2.1.8 85/03/12 16:30:43 lwall
61 * Check i_ptr and i_womp to make sure they aren't null before freeing.
62 * Also allow ed output to be suppressed.
63 *
64 * Revision 1.2.1.7 85/03/12 15:56:13 lwall
65 * Added -p option from jromine@uci-750a.
66 *
67 * Revision 1.2.1.6 85/03/12 12:12:51 lwall
68 * Now checks for normalness of file to patch.
69 *
70 * Revision 1.2.1.5 85/03/12 11:52:12 lwall
71 * Added -D (#ifdef) option from joe@fluke.
72 *
73 * Revision 1.2.1.4 84/12/06 11:14:15 lwall
74 * Made smarter about SCCS subdirectories.
75 *
76 * Revision 1.2.1.3 84/12/05 11:18:43 lwall
77 * Added -l switch to do loose string comparison.
78 *
79 * Revision 1.2.1.2 84/12/04 09:47:13 lwall
80 * Failed hunk count not reset on multiple patch file.
81 *
82 * Revision 1.2.1.1 84/12/04 09:42:37 lwall
83 * Branch for sdcrdcf changes.
84 *
85 * Revision 1.2 84/11/29 13:29:51 lwall
86 * Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed
87 * multiple calls to mktemp(). Will now work on machines that can only
88 * read 32767 chars. Added -R option for diffs with new and old swapped.
89 * Various cosmetic changes.
90 *
91 * Revision 1.1 84/11/09 17:03:58 lwall
92 * Initial revision
93 *
94 */
95/*
96 * 1992-01-15
97 * Modified by Saeko & Kouichi Hirabayashi to fit small memory (64K+64K)
98 * system by adding "#if[n]def SMALL" parts.
99 */
100
101#include "INTERN.h"
102#include "common.h"
103#include "EXTERN.h"
104#include "version.h"
105#include "util.h"
106#include "pch.h"
107#include "inp.h"
108
109/* procedures */
110
111_PROTOTYPE(int main , (int argc , char **argv ));
112_PROTOTYPE(void reinitialize_almost_everything , (void));
113_PROTOTYPE(void get_some_switches , (void));
114_PROTOTYPE(LINENUM locate_hunk , (LINENUM fuzz ));
115_PROTOTYPE(void abort_hunk , (void));
116_PROTOTYPE(void apply_hunk , (LINENUM where ));
117_PROTOTYPE(void init_output , (char *name ));
118_PROTOTYPE(void init_reject , (char *name ));
119_PROTOTYPE(void copy_till , (Reg1 LINENUM lastline ));
120_PROTOTYPE(void spew_output , (void));
121_PROTOTYPE(void dump_line , (LINENUM line ));
122_PROTOTYPE(bool patch_match , (LINENUM base , LINENUM offset , LINENUM fuzz ));
123_PROTOTYPE(bool similar , (Reg1 char *a , Reg2 char *b , Reg3 int len ));
124
125/* Apply a set of diffs as appropriate. */
126
127int main(argc,argv)
128int argc;
129char **argv;
130{
131 LINENUM where;
132 LINENUM newwhere;
133 LINENUM fuzz;
134 LINENUM mymaxfuzz;
135 int hunk = 0;
136 int failed = 0;
137 int failtotal = 0;
138 int i;
139
140 setbuf(stderr, serrbuf);
141 for (i = 0; i<MAXFILEC; i++)
142 filearg[i] = Nullch;
143 Mktemp(TMPOUTNAME);
144 Mktemp(TMPINNAME);
145 Mktemp(TMPREJNAME);
146 Mktemp(TMPPATNAME);
147#ifdef SMALL
148 Mktemp(TMPSTRNAME);
149#endif
150
151 /* parse switches */
152 Argc = argc;
153 Argv = argv;
154 get_some_switches();
155
156 /* make sure we clean up /tmp in case of disaster */
157 set_signals(0);
158
159 for (
160 open_patch_file(filearg[1]);
161 there_is_another_patch();
162 reinitialize_almost_everything()
163 ) { /* for each patch in patch file */
164
165 if (outname == Nullch)
166 outname = savestr(filearg[0]);
167
168 /* initialize the patched file */
169 if (!skip_rest_of_patch)
170 init_output(TMPOUTNAME);
171
172 /* for ed script just up and do it and exit */
173 if (diff_type == ED_DIFF) {
174 do_ed_script();
175 continue;
176 }
177
178 /* initialize reject file */
179 init_reject(TMPREJNAME);
180
181 /* find out where all the lines are */
182 if (!skip_rest_of_patch)
183 scan_input(filearg[0]);
184
185 /* from here on, open no standard i/o files, because malloc */
186 /* might misfire and we can't catch it easily */
187
188 /* apply each hunk of patch */
189 hunk = 0;
190 failed = 0;
191 out_of_mem = FALSE;
192 while (another_hunk()) {
193 hunk++;
194 fuzz = Nulline;
195 mymaxfuzz = pch_context();
196 if (maxfuzz < mymaxfuzz)
197 mymaxfuzz = maxfuzz;
198 if (!skip_rest_of_patch) {
199 do {
200 where = locate_hunk(fuzz);
201 if (hunk == 1 && where == Nulline && !force) {
202 /* dwim for reversed patch? */
203 if (!pch_swap()) {
204 if (fuzz == Nulline)
205 say1(
206"Not enough memory to try swapped hunk! Assuming unswapped.\n");
207 continue;
208 }
209 reverse = !reverse;
210 where = locate_hunk(fuzz); /* try again */
211 if (where == Nulline) { /* didn't find it swapped */
212 if (!pch_swap()) /* put it back to normal */
213 fatal1("Lost hunk on alloc error!\n");
214 reverse = !reverse;
215 }
216 else if (noreverse) {
217 if (!pch_swap()) /* put it back to normal */
218 fatal1("Lost hunk on alloc error!\n");
219 reverse = !reverse;
220 say1(
221"Ignoring previously applied (or reversed) patch.\n");
222 skip_rest_of_patch = TRUE;
223 }
224 else {
225 ask3(
226"%seversed (or previously applied) patch detected! %s -R? [y] ",
227 reverse ? "R" : "Unr",
228 reverse ? "Assume" : "Ignore");
229 if (*buf == 'n') {
230 ask1("Apply anyway? [n] ");
231 if (*buf != 'y')
232 skip_rest_of_patch = TRUE;
233 where = Nulline;
234 reverse = !reverse;
235 if (!pch_swap()) /* put it back to normal */
236 fatal1("Lost hunk on alloc error!\n");
237 }
238 }
239 }
240 } while (!skip_rest_of_patch && where == Nulline &&
241 ++fuzz <= mymaxfuzz);
242
243 if (skip_rest_of_patch) { /* just got decided */
244 Fclose(ofp);
245 ofp = Nullfp;
246 }
247 }
248
249 newwhere = pch_newfirst() + last_offset;
250 if (skip_rest_of_patch) {
251 abort_hunk();
252 failed++;
253 if (verbose)
254 say3("Hunk #%d ignored at %ld.\n", hunk, newwhere);
255 }
256 else if (where == Nulline) {
257 abort_hunk();
258 failed++;
259 if (verbose)
260 say3("Hunk #%d failed at %ld.\n", hunk, newwhere);
261 }
262 else {
263 apply_hunk(where);
264 if (verbose) {
265 say3("Hunk #%d succeeded at %ld", hunk, newwhere);
266 if (fuzz)
267 say2(" with fuzz %ld", fuzz);
268 if (last_offset)
269 say3(" (offset %ld line%s)",
270 last_offset, last_offset==1L?"":"s");
271 say1(".\n");
272 }
273 }
274 }
275
276 if (out_of_mem && using_plan_a) {
277 Argc = Argc_last;
278 Argv = Argv_last;
279 say1("\n\nRan out of memory using Plan A--trying again...\n\n");
280 continue;
281 }
282
283 assert(hunk);
284
285 /* finish spewing out the new file */
286 if (!skip_rest_of_patch)
287 spew_output();
288
289 /* and put the output where desired */
290 ignore_signals();
291 if (!skip_rest_of_patch) {
292 if (move_file(TMPOUTNAME, outname) < 0) {
293 toutkeep = TRUE;
294 chmod(TMPOUTNAME, filemode);
295 }
296 else
297 chmod(outname, filemode);
298 }
299 Fclose(rejfp);
300 rejfp = Nullfp;
301 if (failed) {
302 failtotal += failed;
303 if (!*rejname) {
304 Strcpy(rejname, outname);
305#ifndef FLEXFILENAMES
306 {
307 char *s = rindex(rejname,'/');
308
309 if (!s)
310 s = rejname;
311 if (strlen(s) > 13)
312 if (s[12] == '.') /* try to preserve difference */
313 s[12] = s[13]; /* between .h, .c, .y, etc. */
314 s[13] = '\0';
315 }
316#endif
317 Strcat(rejname, REJEXT);
318 }
319 if (skip_rest_of_patch) {
320 say4("%d out of %d hunks ignored--saving rejects to %s\n",
321 failed, hunk, rejname);
322 }
323 else {
324 say4("%d out of %d hunks failed--saving rejects to %s\n",
325 failed, hunk, rejname);
326 }
327 if (move_file(TMPREJNAME, rejname) < 0)
328 trejkeep = TRUE;
329 }
330 set_signals(1);
331 }
332#ifdef SMALL
333 if (sfp != Nullfp)
334 Fclose(sfp);
335#endif
336 my_exit(failtotal);
337}
338
339/* Prepare to find the next patch to do in the patch file. */
340
341void
342reinitialize_almost_everything()
343{
344 re_patch();
345 re_input();
346
347 input_lines = 0;
348 last_frozen_line = 0;
349
350 filec = 0;
351 if (filearg[0] != Nullch && !out_of_mem) {
352 free(filearg[0]);
353 filearg[0] = Nullch;
354 }
355
356 if (outname != Nullch) {
357 free(outname);
358 outname = Nullch;
359 }
360
361 last_offset = 0;
362
363 diff_type = 0;
364
365 if (revision != Nullch) {
366 free(revision);
367 revision = Nullch;
368 }
369
370 reverse = FALSE;
371 skip_rest_of_patch = FALSE;
372
373 get_some_switches();
374
375 if (filec >= 2)
376 fatal1("You may not change to a different patch file.\n");
377}
378
379/* Process switches and filenames up to next '+' or end of list. */
380
381void
382get_some_switches()
383{
384 Reg1 char *s;
385
386 rejname[0] = '\0';
387 Argc_last = Argc;
388 Argv_last = Argv;
389 if (!Argc)
390 return;
391 for (Argc--,Argv++; Argc; Argc--,Argv++) {
392 s = Argv[0];
393 if (strEQ(s, "+")) {
394 return; /* + will be skipped by for loop */
395 }
396 if (*s != '-' || !s[1]) {
397 if (filec == MAXFILEC)
398 fatal1("Too many file arguments.\n");
399 filearg[filec++] = savestr(s);
400 }
401 else {
402 switch (*++s) {
403 case 'b':
404 origext = savestr(Argv[1]);
405 Argc--,Argv++;
406 break;
407 case 'B':
408 origprae = savestr(Argv[1]);
409 Argc--,Argv++;
410 break;
411 case 'c':
412 diff_type = CONTEXT_DIFF;
413 break;
414 case 'd':
415 if (!*++s) {
416 Argc--,Argv++;
417 s = Argv[0];
418 }
419 if (chdir(s) < 0)
420 fatal2("Can't cd to %s.\n", s);
421 break;
422 case 'D':
423 do_defines = TRUE;
424 if (!*++s) {
425 Argc--,Argv++;
426 s = Argv[0];
427 }
428 if (!isalpha(*s))
429 fatal1("Argument to -D not an identifier.\n");
430 Sprintf(if_defined, "#ifdef %s\n", s);
431 Sprintf(not_defined, "#ifndef %s\n", s);
432 Sprintf(end_defined, "#endif /* %s */\n", s);
433 break;
434 case 'e':
435 diff_type = ED_DIFF;
436 break;
437 case 'f':
438 force = TRUE;
439 break;
440 case 'F':
441 if (*++s == '=')
442 s++;
443 maxfuzz = atoi(s);
444 break;
445 case 'l':
446 canonicalize = TRUE;
447 break;
448 case 'n':
449 diff_type = NORMAL_DIFF;
450 break;
451 case 'N':
452 noreverse = TRUE;
453 break;
454 case 'o':
455 outname = savestr(Argv[1]);
456 Argc--,Argv++;
457 break;
458 case 'p':
459 if (*++s == '=')
460 s++;
461 strippath = atoi(s);
462 break;
463 case 'r':
464 Strcpy(rejname, Argv[1]);
465 Argc--,Argv++;
466 break;
467 case 'R':
468 reverse = TRUE;
469 break;
470 case 's':
471 verbose = FALSE;
472 break;
473 case 'S':
474 skip_rest_of_patch = TRUE;
475 break;
476 case 'v':
477 version();
478 break;
479#ifdef DEBUGGING
480 case 'x':
481 debug = atoi(s+1);
482 break;
483#endif
484 default:
485 fatal2("Unrecognized switch: %s\n", Argv[0]);
486 }
487 }
488 }
489}
490
491/* Attempt to find the right place to apply this hunk of patch. */
492
493LINENUM
494locate_hunk(fuzz)
495LINENUM fuzz;
496{
497 Reg1 LINENUM first_guess = pch_first() + last_offset;
498 Reg2 LINENUM offset;
499 LINENUM pat_lines = pch_ptrn_lines();
500 Reg3 LINENUM max_pos_offset = input_lines - first_guess
501 - pat_lines + 1;
502 Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1
503 + pch_context();
504
505 if (!pat_lines) /* null range matches always */
506 return first_guess;
507 if (max_neg_offset >= first_guess) /* do not try lines < 0 */
508 max_neg_offset = first_guess - 1;
509 if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz))
510 return first_guess;
511 for (offset = 1; ; offset++) {
512 Reg5 bool check_after = (offset <= max_pos_offset);
513 Reg6 bool check_before = (offset <= max_neg_offset);
514
515 if (check_after && patch_match(first_guess, offset, fuzz)) {
516#ifdef DEBUGGING
517 if (debug & 1)
518 say3("Offset changing from %ld to %ld\n", last_offset, offset);
519#endif
520 last_offset = offset;
521 return first_guess+offset;
522 }
523 else if (check_before && patch_match(first_guess, -offset, fuzz)) {
524#ifdef DEBUGGING
525 if (debug & 1)
526 say3("Offset changing from %ld to %ld\n", last_offset, -offset);
527#endif
528 last_offset = -offset;
529 return first_guess-offset;
530 }
531 else if (!check_before && !check_after)
532 return Nulline;
533 }
534}
535
536/* We did not find the pattern, dump out the hunk so they can handle it. */
537
538void
539abort_hunk()
540{
541 Reg1 LINENUM i;
542 Reg2 LINENUM pat_end = pch_end();
543 /* add in last_offset to guess the same as the previous successful hunk */
544 LINENUM oldfirst = pch_first() + last_offset;
545 LINENUM newfirst = pch_newfirst() + last_offset;
546 LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
547 LINENUM newlast = newfirst + pch_repl_lines() - 1;
548 char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : "");
549 char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----");
550
551 fprintf(rejfp, "***************\n");
552 for (i=0; i<=pat_end; i++) {
553 switch (pch_char(i)) {
554 case '*':
555 if (oldlast < oldfirst)
556 fprintf(rejfp, "*** 0%s\n", stars);
557 else if (oldlast == oldfirst)
558 fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
559 else
560 fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
561 break;
562 case '=':
563 if (newlast < newfirst)
564 fprintf(rejfp, "--- 0%s\n", minuses);
565 else if (newlast == newfirst)
566 fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
567 else
568 fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
569 break;
570 case '\n':
571 fprintf(rejfp, "%s", pfetch(i));
572 break;
573 case ' ': case '-': case '+': case '!':
574 fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
575 break;
576 default:
577 say1("Fatal internal error in abort_hunk().\n");
578 abort();
579 }
580 }
581}
582
583/* We found where to apply it (we hope), so do it. */
584
585void
586apply_hunk(where)
587LINENUM where;
588{
589 Reg1 LINENUM old = 1;
590 Reg2 LINENUM lastline = pch_ptrn_lines();
591 Reg3 LINENUM new = lastline+1;
592#define OUTSIDE 0
593#define IN_IFNDEF 1
594#define IN_IFDEF 2
595#define IN_ELSE 3
596 Reg4 int def_state = OUTSIDE;
597 Reg5 bool R_do_defines = do_defines;
598 Reg6 LINENUM pat_end = pch_end();
599
600 where--;
601 while (pch_char(new) == '=' || pch_char(new) == '\n')
602 new++;
603
604 while (old <= lastline) {
605 if (pch_char(old) == '-') {
606 copy_till(where + old - 1);
607 if (R_do_defines) {
608 if (def_state == OUTSIDE) {
609 fputs(not_defined, ofp);
610 def_state = IN_IFNDEF;
611 }
612 else if (def_state == IN_IFDEF) {
613 fputs(else_defined, ofp);
614 def_state = IN_ELSE;
615 }
616 fputs(pfetch(old), ofp);
617 }
618 last_frozen_line++;
619 old++;
620 }
621 else if (new > pat_end)
622 break;
623 else if (pch_char(new) == '+') {
624 copy_till(where + old - 1);
625 if (R_do_defines) {
626 if (def_state == IN_IFNDEF) {
627 fputs(else_defined, ofp);
628 def_state = IN_ELSE;
629 }
630 else if (def_state == OUTSIDE) {
631 fputs(if_defined, ofp);
632 def_state = IN_IFDEF;
633 }
634 }
635 fputs(pfetch(new), ofp);
636 new++;
637 }
638 else {
639 if (pch_char(new) != pch_char(old)) {
640 say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
641 pch_hunk_beg() + old,
642 pch_hunk_beg() + new);
643#ifdef DEBUGGING
644 say3("oldchar = '%c', newchar = '%c'\n",
645 pch_char(old), pch_char(new));
646#endif
647 my_exit(1);
648 }
649 if (pch_char(new) == '!') {
650 copy_till(where + old - 1);
651 if (R_do_defines) {
652 fputs(not_defined, ofp);
653 def_state = IN_IFNDEF;
654 }
655 while (pch_char(old) == '!') {
656 if (R_do_defines) {
657 fputs(pfetch(old), ofp);
658 }
659 last_frozen_line++;
660 old++;
661 }
662 if (R_do_defines) {
663 fputs(else_defined, ofp);
664 def_state = IN_ELSE;
665 }
666 while (pch_char(new) == '!') {
667 fputs(pfetch(new), ofp);
668 new++;
669 }
670 if (R_do_defines) {
671 fputs(end_defined, ofp);
672 def_state = OUTSIDE;
673 }
674 }
675 else {
676 assert(pch_char(new) == ' ');
677 old++;
678 new++;
679 }
680 }
681 }
682 if (new <= pat_end && pch_char(new) == '+') {
683 copy_till(where + old - 1);
684 if (R_do_defines) {
685 if (def_state == OUTSIDE) {
686 fputs(if_defined, ofp);
687 def_state = IN_IFDEF;
688 }
689 else if (def_state == IN_IFNDEF) {
690 fputs(else_defined, ofp);
691 def_state = IN_ELSE;
692 }
693 }
694 while (new <= pat_end && pch_char(new) == '+') {
695 fputs(pfetch(new), ofp);
696 new++;
697 }
698 }
699 if (R_do_defines && def_state != OUTSIDE) {
700 fputs(end_defined, ofp);
701 }
702}
703
704/* Open the new file. */
705
706void
707init_output(name)
708char *name;
709{
710 ofp = fopen(name, "w");
711 if (ofp == Nullfp)
712 fatal2("patch: can't create %s.\n", name);
713}
714
715/* Open a file to put hunks we can't locate. */
716
717void
718init_reject(name)
719char *name;
720{
721 rejfp = fopen(name, "w");
722 if (rejfp == Nullfp)
723 fatal2("patch: can't create %s.\n", name);
724}
725
726/* Copy input file to output, up to wherever hunk is to be applied. */
727
728void
729copy_till(lastline)
730Reg1 LINENUM lastline;
731{
732 Reg2 LINENUM R_last_frozen_line = last_frozen_line;
733
734 if (R_last_frozen_line > lastline)
735 say1("patch: misordered hunks! output will be garbled.\n");
736 while (R_last_frozen_line < lastline) {
737 dump_line(++R_last_frozen_line);
738 }
739 last_frozen_line = R_last_frozen_line;
740}
741
742/* Finish copying the input file to the output file. */
743
744void
745spew_output()
746{
747#ifdef DEBUGGING
748 if (debug & 256)
749 say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line);
750#endif
751 if (input_lines)
752 copy_till(input_lines); /* dump remainder of file */
753 Fclose(ofp);
754 ofp = Nullfp;
755}
756
757/* Copy one line from input to output. */
758
759void
760dump_line(line)
761LINENUM line;
762{
763 Reg1 char *s;
764 Reg2 char R_newline = '\n';
765
766 /* Note: string is not null terminated. */
767 for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ;
768}
769
770/* Does the patch pattern match at line base+offset? */
771
772bool
773patch_match(base, offset, fuzz)
774LINENUM base;
775LINENUM offset;
776LINENUM fuzz;
777{
778 Reg1 LINENUM pline = 1 + fuzz;
779 Reg2 LINENUM iline;
780 Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
781
782 for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) {
783 if (canonicalize) {
784 if (!similar(ifetch(iline, (offset >= 0)),
785 pfetch(pline),
786 pch_line_len(pline) ))
787 return FALSE;
788 }
789 else if (strnNE(ifetch(iline, (offset >= 0)),
790 pfetch(pline),
791 pch_line_len(pline) ))
792 return FALSE;
793 }
794 return TRUE;
795}
796
797/* Do two lines match with canonicalized white space? */
798
799bool
800similar(a,b,len)
801Reg1 char *a;
802Reg2 char *b;
803Reg3 int len;
804{
805 while (len) {
806 if (isspace(*b)) { /* whitespace (or \n) to match? */
807 if (!isspace(*a)) /* no corresponding whitespace? */
808 return FALSE;
809 while (len && isspace(*b) && *b != '\n')
810 b++,len--; /* skip pattern whitespace */
811 while (isspace(*a) && *a != '\n')
812 a++; /* skip target whitespace */
813 if (*a == '\n' || *b == '\n')
814 return (*a == *b); /* should end in sync */
815 }
816 else if (*a++ != *b++) /* match non-whitespace chars */
817 return FALSE;
818 else
819 len--; /* probably not necessary */
820 }
821 return TRUE; /* actually, this is not reached */
822 /* since there is always a \n */
823}
824
825/* Exit with cleanup. */
826
827void
828my_exit(status)
829int status;
830{
831 Unlink(TMPINNAME);
832 if (!toutkeep) {
833 Unlink(TMPOUTNAME);
834 }
835 if (!trejkeep) {
836 Unlink(TMPREJNAME);
837 }
838 Unlink(TMPPATNAME);
839#ifdef SMALL
840 Unlink(TMPSTRNAME);
841#endif
842 exit(status);
843}
Note: See TracBrowser for help on using the repository browser.