Annotation of 43BSDTahoe/new/patch/patch.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.