Annotation of 43BSD/contrib/mh/miscellany/patch/patch.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)patch.c    5.3 (Berkeley) 8/16/85";
        !             3: #endif not lint
        !             4: 
        !             5: /* patch - a program to apply diffs to original files
        !             6:  *
        !             7:  * $Header: patch.c,v 1.3 85/03/26 15:07:43 lwall Exp $
        !             8:  *
        !             9:  * Copyright 1984, Larry Wall
        !            10:  *
        !            11:  * This program may be copied as long as you don't try to make any
        !            12:  * money off of it, or pretend that you wrote it.
        !            13:  *
        !            14:  * $Log:       patch.c,v $
        !            15:  * 85/08/15 van%ucbmonet@berkeley
        !            16:  * Changes for 4.3bsd diff -c.
        !            17:  *
        !            18:  * Revision 1.3  85/03/26  15:07:43  lwall
        !            19:  * Frozen.
        !            20:  * 
        !            21:  * Revision 1.2.1.9  85/03/12  17:03:35  lwall
        !            22:  * Changed pfp->_file to fileno(pfp).
        !            23:  * 
        !            24:  * Revision 1.2.1.8  85/03/12  16:30:43  lwall
        !            25:  * Check i_ptr and i_womp to make sure they aren't null before freeing.
        !            26:  * Also allow ed output to be suppressed.
        !            27:  * 
        !            28:  * Revision 1.2.1.7  85/03/12  15:56:13  lwall
        !            29:  * Added -p option from jromine@uci-750a.
        !            30:  * 
        !            31:  * Revision 1.2.1.6  85/03/12  12:12:51  lwall
        !            32:  * Now checks for normalness of file to patch.
        !            33:  * 
        !            34:  * Revision 1.2.1.5  85/03/12  11:52:12  lwall
        !            35:  * Added -D (#ifdef) option from joe@fluke.
        !            36:  * 
        !            37:  * Revision 1.2.1.4  84/12/06  11:14:15  lwall
        !            38:  * Made smarter about SCCS subdirectories.
        !            39:  * 
        !            40:  * Revision 1.2.1.3  84/12/05  11:18:43  lwall
        !            41:  * Added -l switch to do loose string comparison.
        !            42:  * 
        !            43:  * Revision 1.2.1.2  84/12/04  09:47:13  lwall
        !            44:  * Failed hunk count not reset on multiple patch file.
        !            45:  * 
        !            46:  * Revision 1.2.1.1  84/12/04  09:42:37  lwall
        !            47:  * Branch for sdcrdcf changes.
        !            48:  * 
        !            49:  * Revision 1.2  84/11/29  13:29:51  lwall
        !            50:  * Linted.  Identifiers uniqified.  Fixed i_ptr malloc() bug.  Fixed
        !            51:  * multiple calls to mktemp().  Will now work on machines that can only
        !            52:  * read 32767 chars.  Added -R option for diffs with new and old swapped.
        !            53:  * Various cosmetic changes.
        !            54:  * 
        !            55:  * Revision 1.1  84/11/09  17:03:58  lwall
        !            56:  * Initial revision
        !            57:  * 
        !            58:  */
        !            59: 
        !            60: #define DEBUGGING
        !            61: 
        !            62: /* shut lint up about the following when return value ignored */
        !            63: 
        !            64: #define Signal (void)signal
        !            65: #define Unlink (void)unlink
        !            66: #define Lseek (void)lseek
        !            67: #define Fseek (void)fseek
        !            68: #define Fstat (void)fstat
        !            69: #define Pclose (void)pclose
        !            70: #define Close (void)close
        !            71: #define Fclose (void)fclose
        !            72: #define Fflush (void)fflush
        !            73: #define Sprintf (void)sprintf
        !            74: #define Mktemp (void)mktemp
        !            75: #define Strcpy (void)strcpy
        !            76: #define Strcat (void)strcat
        !            77: 
        !            78: #include <stdio.h>
        !            79: #include <assert.h>
        !            80: #include <sys/types.h>
        !            81: #include <sys/stat.h>
        !            82: #include <ctype.h>
        !            83: #include <signal.h>
        !            84: 
        !            85: /* constants */
        !            86: 
        !            87: #define TRUE (1)
        !            88: #define FALSE (0)
        !            89: 
        !            90: #define MAXHUNKSIZE 500
        !            91: #define MAXLINELEN 1024
        !            92: #define BUFFERSIZE 1024
        !            93: #define ORIGEXT ".orig"
        !            94: #define SCCSPREFIX "s."
        !            95: #define GET "get -e %s"
        !            96: #define RCSSUFFIX ",v"
        !            97: #define CHECKOUT "co -l %s"
        !            98: 
        !            99: /* handy definitions */
        !           100: 
        !           101: #define Null(t) ((t)0)
        !           102: #define Nullch Null(char *)
        !           103: #define Nullfp Null(FILE *)
        !           104: 
        !           105: #define Ctl(ch) (ch & 037)
        !           106: 
        !           107: #define strNE(s1,s2) (strcmp(s1,s2))
        !           108: #define strEQ(s1,s2) (!strcmp(s1,s2))
        !           109: #define strnNE(s1,s2,l) (strncmp(s1,s2,l))
        !           110: #define strnEQ(s1,s2,l) (!strncmp(s1,s2,l))
        !           111: 
        !           112: /* typedefs */
        !           113: 
        !           114: typedef char bool;
        !           115: typedef long LINENUM;                  /* must be signed */
        !           116: typedef unsigned MEM;                  /* what to feed malloc */
        !           117: 
        !           118: /* globals */
        !           119: 
        !           120: int Argc;                              /* guess */
        !           121: char **Argv;
        !           122: 
        !           123: struct stat filestat;                  /* file statistics area */
        !           124: 
        !           125: char serrbuf[BUFSIZ];                  /* buffer for stderr */
        !           126: char buf[MAXLINELEN];                  /* general purpose buffer */
        !           127: FILE *pfp = Nullfp;                    /* patch file pointer */
        !           128: FILE *ofp = Nullfp;                    /* output file pointer */
        !           129: FILE *rejfp = Nullfp;                  /* reject file pointer */
        !           130: 
        !           131: LINENUM input_lines = 0;               /* how long is input file in lines */
        !           132: LINENUM last_frozen_line = 0;          /* how many input lines have been */
        !           133:                                        /* irretractibly output */
        !           134: 
        !           135: #define MAXFILEC 2
        !           136: int filec = 0;                         /* how many file arguments? */
        !           137: char *filearg[MAXFILEC];
        !           138: 
        !           139: char *outname = Nullch;
        !           140: char rejname[128];
        !           141: 
        !           142: char *origext = Nullch;
        !           143: 
        !           144: char TMPOUTNAME[] = "/tmp/patchoXXXXXX";
        !           145: char TMPINNAME[] = "/tmp/patchiXXXXXX";        /* you might want /usr/tmp here */
        !           146: char TMPREJNAME[] = "/tmp/patchrXXXXXX";
        !           147: char TMPPATNAME[] = "/tmp/patchpXXXXXX";
        !           148: 
        !           149: LINENUM last_offset = 0;
        !           150: #ifdef DEBUGGING
        !           151: int debug = 0;
        !           152: #endif
        !           153: bool verbose = TRUE;
        !           154: bool reverse = FALSE;
        !           155: bool usepath = FALSE;
        !           156: bool canonicalize = FALSE;
        !           157: 
        !           158: #define CONTEXT_DIFF 1
        !           159: #define NORMAL_DIFF 2
        !           160: #define ED_DIFF 3
        !           161: #define NEW_CONTEXT_DIFF 4
        !           162: int diff_type = 0;
        !           163: 
        !           164: int do_defines = 0;                    /* patch using ifdef, ifndef, etc. */
        !           165: char if_defined[128];                  /* #ifdef xyzzy */
        !           166: char not_defined[128];                 /* #ifndef xyzzy */
        !           167: char else_defined[] = "#else\n";       /* #else */
        !           168: char end_defined[128];                 /* #endif xyzzy */
        !           169: 
        !           170: char *revision = Nullch;               /* prerequisite revision, if any */
        !           171: 
        !           172: /* procedures */
        !           173: 
        !           174: LINENUM locate_hunk();
        !           175: bool patch_match();
        !           176: bool similar();
        !           177: char *malloc();
        !           178: char *savestr();
        !           179: char *strcpy();
        !           180: char *strcat();
        !           181: char *sprintf();               /* usually */
        !           182: int my_exit();
        !           183: bool rev_in_string();
        !           184: char *fetchname();
        !           185: long atol();
        !           186: long lseek();
        !           187: char *mktemp();
        !           188: 
        !           189: /* patch type */
        !           190: 
        !           191: bool there_is_another_patch();
        !           192: bool another_hunk();
        !           193: char *pfetch();
        !           194: int pch_line_len();
        !           195: LINENUM pch_first();
        !           196: LINENUM pch_ptrn_lines();
        !           197: LINENUM pch_newfirst();
        !           198: LINENUM pch_repl_lines();
        !           199: LINENUM pch_end();
        !           200: LINENUM pch_context();
        !           201: LINENUM pch_hunk_beg();
        !           202: char pch_char();
        !           203: char *pfetch();
        !           204: char *pgets();
        !           205: 
        !           206: /* input file type */
        !           207: 
        !           208: char *ifetch();
        !           209: 
        !           210: /* apply a context patch to a named file */
        !           211: 
        !           212: main(argc,argv)
        !           213: int argc;
        !           214: char **argv;
        !           215: {
        !           216:     LINENUM where;
        !           217:     int hunk = 0;
        !           218:     int failed = 0;
        !           219:     int i;
        !           220: 
        !           221:     setbuf(stderr,serrbuf);
        !           222:     for (i = 0; i<MAXFILEC; i++)
        !           223:        filearg[i] = Nullch;
        !           224:     Mktemp(TMPOUTNAME);
        !           225:     Mktemp(TMPINNAME);
        !           226:     Mktemp(TMPREJNAME);
        !           227:     Mktemp(TMPPATNAME);
        !           228: 
        !           229:     /* parse switches */
        !           230:     Argc = argc;
        !           231:     Argv = argv;
        !           232:     get_some_switches();
        !           233:     
        !           234:     /* make sure we clean up /tmp in case of disaster */
        !           235:     set_signals();
        !           236: 
        !           237:     for (
        !           238:        open_patch_file(filearg[1]);
        !           239:        there_is_another_patch();
        !           240:        reinitialize_almost_everything()
        !           241:     ) {                                        /* for each patch in patch file */
        !           242: 
        !           243:        if (outname == Nullch)
        !           244:            outname = savestr(filearg[0]);
        !           245:     
        !           246:        /* initialize the patched file */
        !           247:        init_output(TMPOUTNAME);
        !           248:     
        !           249:        /* for ed script just up and do it and exit */
        !           250:        if (diff_type == ED_DIFF) {
        !           251:            do_ed_script();
        !           252:            continue;
        !           253:        }
        !           254:     
        !           255:        /* initialize reject file */
        !           256:        init_reject(TMPREJNAME);
        !           257:     
        !           258:        /* find out where all the lines are */
        !           259:        scan_input(filearg[0]);
        !           260:     
        !           261:        /* from here on, open no standard i/o files, because malloc */
        !           262:        /* might misfire */
        !           263:     
        !           264:        /* apply each hunk of patch */
        !           265:        hunk = 0;
        !           266:        failed = 0;
        !           267:        while (another_hunk()) {
        !           268:            hunk++;
        !           269:            where = locate_hunk();
        !           270:            if (hunk == 1 && where == Null(LINENUM)) {
        !           271:                                        /* dwim for reversed patch? */
        !           272:                pch_swap();
        !           273:                reverse = !reverse;
        !           274:                where = locate_hunk();  /* try again */
        !           275:                if (where == Null(LINENUM)) {
        !           276:                    pch_swap();         /* no, put it back to normal */
        !           277:                    reverse = !reverse;
        !           278:                }
        !           279:                else {
        !           280:                    say("%seversed (or previously applied) patch detected!  %s -R.\n",
        !           281:                        reverse ? "R" : "Unr",
        !           282:                        reverse ? "Assuming" : "Ignoring");
        !           283:                }
        !           284:            }
        !           285:            if (where == Null(LINENUM)) {
        !           286:                abort_hunk();
        !           287:                failed++;
        !           288:                if (verbose)
        !           289:                    say("Hunk #%d failed.\n",hunk);
        !           290:            }
        !           291:            else {
        !           292:                apply_hunk(where);
        !           293:                if (verbose)
        !           294:                    if (last_offset)
        !           295:                        say("Hunk #%d succeeded (offset %d line%s).\n",
        !           296:                          hunk,last_offset,last_offset==1?"":"s");
        !           297:                    else
        !           298:                        say("Hunk #%d succeeded.\n", hunk);
        !           299:            }
        !           300:        }
        !           301:     
        !           302:        assert(hunk);
        !           303:     
        !           304:        /* finish spewing out the new file */
        !           305:        spew_output();
        !           306:        
        !           307:        /* and put the output where desired */
        !           308:        ignore_signals();
        !           309:        move_file(TMPOUTNAME,outname);
        !           310:        Fclose(rejfp);
        !           311:        rejfp = Nullfp;
        !           312:        if (failed) {
        !           313:            if (!*rejname) {
        !           314:                Strcpy(rejname, outname);
        !           315:                Strcat(rejname, ".rej");
        !           316:            }
        !           317:            say("%d out of %d hunks failed--saving rejects to %s\n",
        !           318:                failed, hunk, rejname);
        !           319:            move_file(TMPREJNAME,rejname);
        !           320:        }
        !           321:        set_signals();
        !           322:     }
        !           323:     my_exit(0);
        !           324: }
        !           325: 
        !           326: reinitialize_almost_everything()
        !           327: {
        !           328:     re_patch();
        !           329:     re_input();
        !           330: 
        !           331:     input_lines = 0;
        !           332:     last_frozen_line = 0;
        !           333: 
        !           334:     filec = 0;
        !           335:     if (filearg[0] != Nullch) {
        !           336:        free(filearg[0]);
        !           337:        filearg[0] = Nullch;
        !           338:     }
        !           339: 
        !           340:     if (outname != Nullch) {
        !           341:        free(outname);
        !           342:        outname = Nullch;
        !           343:     }
        !           344: 
        !           345:     last_offset = 0;
        !           346: 
        !           347:     diff_type = 0;
        !           348: 
        !           349:     if (revision != Nullch) {
        !           350:        free(revision);
        !           351:        revision = Nullch;
        !           352:     }
        !           353: 
        !           354:     reverse = FALSE;
        !           355: 
        !           356:     get_some_switches();
        !           357: 
        !           358:     if (filec >= 2)
        !           359:        fatal("You may not change to a different patch file.\n");
        !           360: }
        !           361: 
        !           362: get_some_switches()
        !           363: {
        !           364:     register char *s;
        !           365: 
        !           366:     rejname[0] = '\0';
        !           367:     if (!Argc)
        !           368:        return;
        !           369:     for (Argc--,Argv++; Argc; Argc--,Argv++) {
        !           370:        s = Argv[0];
        !           371:        if (strEQ(s,"+")) {
        !           372:            return;                     /* + will be skipped by for loop */
        !           373:        }
        !           374:        if (*s != '-' || !s[1]) {
        !           375:            if (filec == MAXFILEC)
        !           376:                fatal("Too many file arguments.\n");
        !           377:            filearg[filec++] = savestr(s);
        !           378:        }
        !           379:        else {
        !           380:            switch (*++s) {
        !           381:            case 'b':
        !           382:                origext = savestr(Argv[1]);
        !           383:                Argc--,Argv++;
        !           384:                break;
        !           385:            case 'c':
        !           386:                diff_type = CONTEXT_DIFF;
        !           387:                break;
        !           388:            case 'd':
        !           389:                if (chdir(Argv[1]) < 0)
        !           390:                    fatal("Can't cd to %s.\n",Argv[1]);
        !           391:                Argc--,Argv++;
        !           392:                break;
        !           393:            case 'D':
        !           394:                do_defines++;
        !           395:                Sprintf(if_defined, "#ifdef %s\n", Argv[1]);
        !           396:                Sprintf(not_defined, "#ifndef %s\n", Argv[1]);
        !           397:                Sprintf(end_defined, "#endif %s\n", Argv[1]);
        !           398:                Argc--,Argv++;
        !           399:                break;
        !           400:            case 'e':
        !           401:                diff_type = ED_DIFF;
        !           402:                break;
        !           403:            case 'l':
        !           404:                canonicalize = TRUE;
        !           405:                break;
        !           406:            case 'n':
        !           407:                diff_type = NORMAL_DIFF;
        !           408:                break;
        !           409:            case 'o':
        !           410:                outname = savestr(Argv[1]);
        !           411:                Argc--,Argv++;
        !           412:                break;
        !           413:            case 'p':
        !           414:                usepath = TRUE; /* do not strip path names */
        !           415:                break;
        !           416:            case 'r':
        !           417:                Strcpy(rejname,Argv[1]);
        !           418:                Argc--,Argv++;
        !           419:                break;
        !           420:            case 'R':
        !           421:                reverse = TRUE;
        !           422:                break;
        !           423:            case 's':
        !           424:                verbose = FALSE;
        !           425:                break;
        !           426: #ifdef DEBUGGING
        !           427:            case 'x':
        !           428:                debug = atoi(s+1);
        !           429:                break;
        !           430: #endif
        !           431:            default:
        !           432:                fatal("Unrecognized switch: %s\n",Argv[0]);
        !           433:            }
        !           434:        }
        !           435:     }
        !           436: }
        !           437: 
        !           438: LINENUM
        !           439: locate_hunk()
        !           440: {
        !           441:     register LINENUM first_guess = pch_first() + last_offset;
        !           442:     register LINENUM offset;
        !           443:     LINENUM pat_lines = pch_ptrn_lines();
        !           444:     register LINENUM max_pos_offset = input_lines - first_guess
        !           445:                                - pat_lines + 1; 
        !           446:     register LINENUM max_neg_offset = first_guess - last_frozen_line - 1
        !           447:                                - pch_context();
        !           448: 
        !           449:     if (!pat_lines)                    /* null range matches always */
        !           450:        return first_guess;
        !           451:     if (max_neg_offset >= first_guess) /* do not try lines < 0 */
        !           452:        max_neg_offset = first_guess - 1;
        !           453:     if (first_guess <= input_lines && patch_match(first_guess,(LINENUM)0))
        !           454:        return first_guess;
        !           455:     for (offset = 1; ; offset++) {
        !           456:        bool check_after = (offset <= max_pos_offset);
        !           457:        bool check_before = (offset <= max_pos_offset);
        !           458: 
        !           459:        if (check_after && patch_match(first_guess,offset)) {
        !           460: #ifdef DEBUGGING
        !           461:            if (debug & 1)
        !           462:                printf("Offset changing from %d to %d\n",last_offset,offset);
        !           463: #endif
        !           464:            last_offset = offset;
        !           465:            return first_guess+offset;
        !           466:        }
        !           467:        else if (check_before && patch_match(first_guess,-offset)) {
        !           468: #ifdef DEBUGGING
        !           469:            if (debug & 1)
        !           470:                printf("Offset changing from %d to %d\n",last_offset,-offset);
        !           471: #endif
        !           472:            last_offset = -offset;
        !           473:            return first_guess-offset;
        !           474:        }
        !           475:        else if (!check_before && !check_after)
        !           476:            return Null(LINENUM);
        !           477:     }
        !           478: }
        !           479: 
        !           480: /* we did not find the pattern, dump out the hunk so they can handle it */
        !           481: 
        !           482: abort_hunk()
        !           483: {
        !           484:     register LINENUM i;
        !           485:     register LINENUM pat_end = pch_end();
        !           486:     /* add in last_offset to guess the same as the previous successful hunk */
        !           487:     int oldfirst = pch_first() + last_offset;
        !           488:     int newfirst = pch_newfirst() + last_offset;
        !           489:     int oldlast = oldfirst + pch_ptrn_lines() - 1;
        !           490:     int newlast = newfirst + pch_repl_lines() - 1;
        !           491: 
        !           492:     fprintf(rejfp,"***************\n");
        !           493:     for (i=0; i<=pat_end; i++) {
        !           494:        switch (pch_char(i)) {
        !           495:        case '*':
        !           496:            fprintf(rejfp,"*** %d,%d\n", oldfirst, oldlast);
        !           497:            break;
        !           498:        case '=':
        !           499:            fprintf(rejfp,"--- %d,%d -----\n", newfirst, newlast);
        !           500:            break;
        !           501:        case '\n':
        !           502:            fprintf(rejfp,"%s", pfetch(i));
        !           503:            break;
        !           504:        case ' ': case '-': case '+': case '!':
        !           505:            fprintf(rejfp,"%c %s", pch_char(i), pfetch(i));
        !           506:            break;
        !           507:        default:
        !           508:            say("Fatal internal error in abort_hunk().\n"); 
        !           509:            abort();
        !           510:        }
        !           511:     }
        !           512: }
        !           513: 
        !           514: /* we found where to apply it (we hope), so do it */
        !           515: 
        !           516: apply_hunk(where)
        !           517: LINENUM where;
        !           518: {
        !           519:     register LINENUM old = 1;
        !           520:     register LINENUM lastline = pch_ptrn_lines();
        !           521:     register LINENUM new = lastline+1;
        !           522:     register int def_state = 0;        /* -1 = ifndef, 1 = ifdef */
        !           523: 
        !           524:     where--;
        !           525:     while (pch_char(new) == '=' || pch_char(new) == '\n')
        !           526:        new++;
        !           527:     
        !           528:     while (old <= lastline) {
        !           529:        if (pch_char(old) == '-') {
        !           530:            copy_till(where + old - 1);
        !           531:            if (do_defines) {
        !           532:                if (def_state == 0) {
        !           533:                    fputs(not_defined, ofp);
        !           534:                    def_state = -1;
        !           535:                } else
        !           536:                if (def_state == 1) {
        !           537:                    fputs(else_defined, ofp);
        !           538:                    def_state = 2;
        !           539:                }
        !           540:                fputs(pfetch(old), ofp);
        !           541:            }
        !           542:            last_frozen_line++;
        !           543:            old++;
        !           544:        }
        !           545:        else if (pch_char(new) == '+') {
        !           546:            copy_till(where + old - 1);
        !           547:            if (do_defines) {
        !           548:                if (def_state == -1) {
        !           549:                    fputs(else_defined, ofp);
        !           550:                    def_state = 2;
        !           551:                } else
        !           552:                if (def_state == 0) {
        !           553:                    fputs(if_defined, ofp);
        !           554:                    def_state = 1;
        !           555:                }
        !           556:            }
        !           557:            fputs(pfetch(new),ofp);
        !           558:            new++;
        !           559:        }
        !           560:        else {
        !           561:            if (pch_char(new) != pch_char(old)) {
        !           562:                say("Out-of-sync patch, lines %d,%d\n",
        !           563:                    pch_hunk_beg() + old - 1,
        !           564:                    pch_hunk_beg() + new - 1);
        !           565: #ifdef DEBUGGING
        !           566:                printf("oldchar = '%c', newchar = '%c'\n",
        !           567:                    pch_char(old), pch_char(new));
        !           568: #endif
        !           569:                my_exit(1);
        !           570:            }
        !           571:            if (pch_char(new) == '!') {
        !           572:                copy_till(where + old - 1);
        !           573:                if (do_defines) {
        !           574:                   fputs(not_defined,ofp);
        !           575:                   def_state = -1;
        !           576:                }
        !           577:                while (pch_char(old) == '!') {
        !           578:                    if (do_defines) {
        !           579:                        fputs(pfetch(old),ofp);
        !           580:                    }
        !           581:                    last_frozen_line++;
        !           582:                    old++;
        !           583:                }
        !           584:                if (do_defines) {
        !           585:                    fputs(else_defined, ofp);
        !           586:                    def_state = 2;
        !           587:                }
        !           588:                while (pch_char(new) == '!') {
        !           589:                    fputs(pfetch(new),ofp);
        !           590:                    new++;
        !           591:                }
        !           592:                if (do_defines) {
        !           593:                    fputs(end_defined, ofp);
        !           594:                    def_state = 0;
        !           595:                }
        !           596:            }
        !           597:            else {
        !           598:                assert(pch_char(new) == ' ');
        !           599:                old++;
        !           600:                new++;
        !           601:            }
        !           602:        }
        !           603:     }
        !           604:     if (new <= pch_end() && pch_char(new) == '+') {
        !           605:        copy_till(where + old - 1);
        !           606:        if (do_defines) {
        !           607:            if (def_state == 0) {
        !           608:                fputs(if_defined, ofp);
        !           609:                def_state = 1;
        !           610:            } else
        !           611:            if (def_state == -1) {
        !           612:                fputs(else_defined, ofp);
        !           613:                def_state = 2;
        !           614:            }
        !           615:        }
        !           616:        while (new <= pch_end() && pch_char(new) == '+') {
        !           617:            fputs(pfetch(new),ofp);
        !           618:            new++;
        !           619:        }
        !           620:     }
        !           621:     if (do_defines && def_state) {
        !           622:        fputs(end_defined, ofp);
        !           623:     }
        !           624: }
        !           625: 
        !           626: do_ed_script()
        !           627: {
        !           628:     FILE *pipefp, *popen();
        !           629:     bool this_line_is_command = FALSE;
        !           630:     register char *t;
        !           631:     long beginning_of_this_line;
        !           632: 
        !           633:     Unlink(TMPOUTNAME);
        !           634:     copy_file(filearg[0],TMPOUTNAME);
        !           635:     if (verbose)
        !           636:        Sprintf(buf,"/bin/ed %s",TMPOUTNAME);
        !           637:     else
        !           638:        Sprintf(buf,"/bin/ed - %s",TMPOUTNAME);
        !           639:     pipefp = popen(buf,"w");
        !           640:     for (;;) {
        !           641:        beginning_of_this_line = ftell(pfp);
        !           642:        if (pgets(buf,sizeof buf,pfp) == Nullch) {
        !           643:            next_intuit_at(beginning_of_this_line);
        !           644:            break;
        !           645:        }
        !           646:        for (t=buf; isdigit(*t) || *t == ','; t++) ;
        !           647:        this_line_is_command = (isdigit(*buf) &&
        !           648:          (*t == 'd' || *t == 'c' || *t == 'a') );
        !           649:        if (this_line_is_command) {
        !           650:            fputs(buf,pipefp);
        !           651:            if (*t != 'd') {
        !           652:                while (pgets(buf,sizeof buf,pfp) != Nullch) {
        !           653:                    fputs(buf,pipefp);
        !           654:                    if (strEQ(buf,".\n"))
        !           655:                        break;
        !           656:                }
        !           657:            }
        !           658:        }
        !           659:        else {
        !           660:            next_intuit_at(beginning_of_this_line);
        !           661:            break;
        !           662:        }
        !           663:     }
        !           664:     fprintf(pipefp,"w\n");
        !           665:     fprintf(pipefp,"q\n");
        !           666:     Fflush(pipefp);
        !           667:     Pclose(pipefp);
        !           668:     ignore_signals();
        !           669:     move_file(TMPOUTNAME,outname);
        !           670:     set_signals();
        !           671: }
        !           672: 
        !           673: init_output(name)
        !           674: char *name;
        !           675: {
        !           676:     ofp = fopen(name,"w");
        !           677:     if (ofp == Nullfp)
        !           678:        fatal("patch: can't create %s.\n",name);
        !           679: }
        !           680: 
        !           681: init_reject(name)
        !           682: char *name;
        !           683: {
        !           684:     rejfp = fopen(name,"w");
        !           685:     if (rejfp == Nullfp)
        !           686:        fatal("patch: can't create %s.\n",name);
        !           687: }
        !           688: 
        !           689: move_file(from,to)
        !           690: char *from, *to;
        !           691: {
        !           692:     char bakname[512];
        !           693:     register char *s;
        !           694:     int fromfd;
        !           695:     register int i;
        !           696: 
        !           697:     /* to stdout? */
        !           698: 
        !           699:     if (strEQ(to,"-")) {
        !           700: #ifdef DEBUGGING
        !           701:        if (debug & 4)
        !           702:            say("Moving %s to stdout.\n",from);
        !           703: #endif
        !           704:        fromfd = open(from,0);
        !           705:        if (fromfd < 0)
        !           706:            fatal("patch: internal error, can't reopen %s\n",from);
        !           707:        while ((i=read(fromfd,buf,sizeof buf)) > 0)
        !           708:            if (write(1,buf,i) != 1)
        !           709:                fatal("patch: write failed\n");
        !           710:        Close(fromfd);
        !           711:        return;
        !           712:     }
        !           713: 
        !           714:     Strcpy(bakname,to);
        !           715:     Strcat(bakname,origext?origext:ORIGEXT);
        !           716:     if (stat(to,&filestat) >= 0) {     /* output file exists */
        !           717:        dev_t to_device = filestat.st_dev;
        !           718:        ino_t to_inode  = filestat.st_ino;
        !           719:        char *simplename = bakname;
        !           720:        
        !           721:        for (s=bakname; *s; s++) {
        !           722:            if (*s == '/')
        !           723:                simplename = s+1;
        !           724:        }
        !           725:        /* find a backup name that is not the same file */
        !           726:        while (stat(bakname,&filestat) >= 0 &&
        !           727:                to_device == filestat.st_dev && to_inode == filestat.st_ino) {
        !           728:            for (s=simplename; *s && !islower(*s); s++) ;
        !           729:            if (*s)
        !           730:                *s = toupper(*s);
        !           731:            else
        !           732:                Strcpy(simplename, simplename+1);
        !           733:        }
        !           734:        while (unlink(bakname) >= 0) ;  /* while() is for benefit of Eunice */
        !           735: #ifdef DEBUGGING
        !           736:        if (debug & 4)
        !           737:            say("Moving %s to %s.\n",to,bakname);
        !           738: #endif
        !           739:        if (link(to,bakname) < 0) {
        !           740:            say("patch: can't backup %s, output is in %s\n",
        !           741:                to,from);
        !           742:            return;
        !           743:        }
        !           744:        while (unlink(to) >= 0) ;
        !           745:     }
        !           746: #ifdef DEBUGGING
        !           747:     if (debug & 4)
        !           748:        say("Moving %s to %s.\n",from,to);
        !           749: #endif
        !           750:     if (link(from,to) < 0) {           /* different file system? */
        !           751:        int tofd;
        !           752:        
        !           753:        tofd = creat(to,0666);
        !           754:        if (tofd < 0) {
        !           755:            say("patch: can't create %s, output is in %s.\n",
        !           756:              to, from);
        !           757:            return;
        !           758:        }
        !           759:        fromfd = open(from,0);
        !           760:        if (fromfd < 0)
        !           761:            fatal("patch: internal error, can't reopen %s\n",from);
        !           762:        while ((i=read(fromfd,buf,sizeof buf)) > 0)
        !           763:            if (write(tofd,buf,i) != i)
        !           764:                fatal("patch: write failed\n");
        !           765:        Close(fromfd);
        !           766:        Close(tofd);
        !           767:     }
        !           768:     Unlink(from);
        !           769: }
        !           770: 
        !           771: copy_file(from,to)
        !           772: char *from, *to;
        !           773: {
        !           774:     int tofd;
        !           775:     int fromfd;
        !           776:     register int i;
        !           777:     
        !           778:     tofd = creat(to,0666);
        !           779:     if (tofd < 0)
        !           780:        fatal("patch: can't create %s.\n", to);
        !           781:     fromfd = open(from,0);
        !           782:     if (fromfd < 0)
        !           783:        fatal("patch: internal error, can't reopen %s\n",from);
        !           784:     while ((i=read(fromfd,buf,sizeof buf)) > 0)
        !           785:        if (write(tofd,buf,i) != i)
        !           786:            fatal("patch: write (%s) failed\n", to);
        !           787:     Close(fromfd);
        !           788:     Close(tofd);
        !           789: }
        !           790: 
        !           791: copy_till(lastline)
        !           792: register LINENUM lastline;
        !           793: {
        !           794:     if (last_frozen_line > lastline)
        !           795:        say("patch: misordered hunks! output will be garbled.\n");
        !           796:     while (last_frozen_line < lastline) {
        !           797:        dump_line(++last_frozen_line);
        !           798:     }
        !           799: }
        !           800: 
        !           801: spew_output()
        !           802: {
        !           803:     copy_till(input_lines);            /* dump remainder of file */
        !           804:     Fclose(ofp);
        !           805:     ofp = Nullfp;
        !           806: }
        !           807: 
        !           808: dump_line(line)
        !           809: LINENUM line;
        !           810: {
        !           811:     register char *s;
        !           812: 
        !           813:     for (s=ifetch(line,0); putc(*s,ofp) != '\n'; s++) ;
        !           814: }
        !           815: 
        !           816: /* does the patch pattern match at line base+offset? */
        !           817: 
        !           818: bool
        !           819: patch_match(base,offset)
        !           820: LINENUM base;
        !           821: LINENUM offset;
        !           822: {
        !           823:     register LINENUM pline;
        !           824:     register LINENUM iline;
        !           825:     register LINENUM pat_lines = pch_ptrn_lines();
        !           826: 
        !           827:     for (pline = 1, iline=base+offset; pline <= pat_lines; pline++,iline++) {
        !           828:        if (canonicalize) {
        !           829:            if (!similar(ifetch(iline,(offset >= 0)),
        !           830:                         pfetch(pline),
        !           831:                         pch_line_len(pline) ))
        !           832:                return FALSE;
        !           833:        }
        !           834:        else if (strnNE(ifetch(iline,(offset >= 0)),
        !           835:                   pfetch(pline),
        !           836:                   pch_line_len(pline) ))
        !           837:            return FALSE;
        !           838:     }
        !           839:     return TRUE;
        !           840: }
        !           841: 
        !           842: /* match two lines with canonicalized white space */
        !           843: 
        !           844: bool
        !           845: similar(a,b,len)
        !           846: register char *a, *b;
        !           847: register int len;
        !           848: {
        !           849:     while (len) {
        !           850:        if (isspace(*b)) {              /* whitespace (or \n) to match? */
        !           851:            if (!isspace(*a))           /* no corresponding whitespace? */
        !           852:                return FALSE;
        !           853:            while (len && isspace(*b) && *b != '\n')
        !           854:                b++,len--;              /* skip pattern whitespace */
        !           855:            while (isspace(*a) && *a != '\n')
        !           856:                a++;                    /* skip target whitespace */
        !           857:            if (*a == '\n' || *b == '\n')
        !           858:                return (*a == *b);      /* should end in sync */
        !           859:        }
        !           860:        else if (*a++ != *b++)          /* match non-whitespace chars */
        !           861:            return FALSE;
        !           862:        else
        !           863:            len--;                      /* probably not necessary */
        !           864:     }
        !           865:     return TRUE;                       /* actually, this is not reached */
        !           866:                                        /* since there is always a \n */
        !           867: }
        !           868: 
        !           869: /* input file with indexable lines abstract type */
        !           870: 
        !           871: bool using_plan_a = TRUE;
        !           872: static long i_size;                    /* size of the input file */
        !           873: static char *i_womp;                   /* plan a buffer for entire file */
        !           874: static char **i_ptr;                   /* pointers to lines in i_womp */
        !           875: 
        !           876: static int tifd = -1;                  /* plan b virtual string array */
        !           877: static char *tibuf[2];                 /* plan b buffers */
        !           878: static LINENUM tiline[2] = {-1,-1};    /* 1st line in each buffer */
        !           879: static LINENUM lines_per_buf;          /* how many lines per buffer */
        !           880: static int tireclen;                   /* length of records in tmp file */
        !           881: 
        !           882: re_input()
        !           883: {
        !           884:     if (using_plan_a) {
        !           885:        i_size = 0;
        !           886:        /*NOSTRICT*/
        !           887:        if (i_ptr != Null(char**))
        !           888:            free((char *)i_ptr);
        !           889:        if (i_womp != Nullch)
        !           890:            free(i_womp);
        !           891:        i_womp = Nullch;
        !           892:        i_ptr = Null(char **);
        !           893:     }
        !           894:     else {
        !           895:        using_plan_a = TRUE;            /* maybe the next one is smaller */
        !           896:        Close(tifd);
        !           897:        tifd = -1;
        !           898:        free(tibuf[0]);
        !           899:        free(tibuf[1]);
        !           900:        tibuf[0] = tibuf[1] = Nullch;
        !           901:        tiline[0] = tiline[1] = -1;
        !           902:        tireclen = 0;
        !           903:     }
        !           904: }
        !           905: 
        !           906: scan_input(filename)
        !           907: char *filename;
        !           908: {
        !           909:     bool plan_a();
        !           910: 
        !           911:     if (!plan_a(filename))
        !           912:        plan_b(filename);
        !           913: }
        !           914: 
        !           915: /* try keeping everything in memory */
        !           916: 
        !           917: bool
        !           918: plan_a(filename)
        !           919: char *filename;
        !           920: {
        !           921:     int ifd;
        !           922:     register char *s;
        !           923:     register LINENUM iline;
        !           924: 
        !           925:     if (stat(filename,&filestat) < 0) {
        !           926:        Sprintf(buf,"RCS/%s%s",filename,RCSSUFFIX);
        !           927:        if (stat(buf,&filestat) >= 0 || stat(buf+4,&filestat) >= 0) {
        !           928:            Sprintf(buf,CHECKOUT,filename);
        !           929:            if (verbose)
        !           930:                say("Can't find %s--attempting to check it out from RCS.\n",
        !           931:                    filename);
        !           932:            if (system(buf) || stat(filename,&filestat))
        !           933:                fatal("Can't check out %s.\n",filename);
        !           934:        }
        !           935:        else {
        !           936:            Sprintf(buf,"SCCS/%s%s",SCCSPREFIX,filename);
        !           937:            if (stat(buf,&filestat) >= 0 || stat(buf+5,&filestat) >= 0) {
        !           938:                Sprintf(buf,GET,filename);
        !           939:                if (verbose)
        !           940:                    say("Can't find %s--attempting to get it from SCCS.\n",
        !           941:                        filename);
        !           942:                if (system(buf) || stat(filename,&filestat))
        !           943:                    fatal("Can't get %s.\n",filename);
        !           944:            }
        !           945:            else
        !           946:                fatal("Can't find %s.\n",filename);
        !           947:        }
        !           948:     }
        !           949:     if ((filestat.st_mode & S_IFMT) & ~S_IFREG)
        !           950:        fatal("%s is not a normal file--can't patch.\n",filename);
        !           951:     i_size = filestat.st_size;
        !           952:     /*NOSTRICT*/
        !           953:     i_womp = malloc((MEM)(i_size+2));
        !           954:     if (i_womp == Nullch)
        !           955:        return FALSE;
        !           956:     if ((ifd = open(filename,0)) < 0)
        !           957:        fatal("Can't open file %s\n",filename);
        !           958:     /*NOSTRICT*/
        !           959:     if (read(ifd,i_womp,(int)i_size) != i_size) {
        !           960:        Close(ifd);
        !           961:        free(i_womp);
        !           962:        return FALSE;
        !           963:     }
        !           964:     Close(ifd);
        !           965:     if (i_womp[i_size-1] != '\n')
        !           966:        i_womp[i_size++] = '\n';
        !           967:     i_womp[i_size] = '\0';
        !           968: 
        !           969:     /* count the lines in the buffer so we know how many pointers we need */
        !           970: 
        !           971:     iline = 0;
        !           972:     for (s=i_womp; *s; s++) {
        !           973:        if (*s == '\n')
        !           974:            iline++;
        !           975:     }
        !           976:     /*NOSTRICT*/
        !           977:     i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
        !           978:     if (i_ptr == Null(char **)) {      /* shucks, it was a near thing */
        !           979:        free((char *)i_womp);
        !           980:        return FALSE;
        !           981:     }
        !           982:     
        !           983:     /* now scan the buffer and build pointer array */
        !           984: 
        !           985:     iline = 1;
        !           986:     i_ptr[iline] = i_womp;
        !           987:     for (s=i_womp; *s; s++) {
        !           988:        if (*s == '\n')
        !           989:            i_ptr[++iline] = s+1;       /* these are NOT null terminated */
        !           990:     }
        !           991:     input_lines = iline - 1;
        !           992: 
        !           993:     /* now check for revision, if any */
        !           994: 
        !           995:     if (revision != Nullch) { 
        !           996:        if (!rev_in_string(i_womp)) {
        !           997:            ask("This file doesn't appear to be the %s version--patch anyway? [n] ",
        !           998:                revision);
        !           999:            if (*buf != 'y')
        !          1000:                fatal("Aborted.\n");
        !          1001:        }
        !          1002:        else if (verbose)
        !          1003:            say("Good.  This file appears to be the %s version.\n",
        !          1004:                revision);
        !          1005:     }
        !          1006:     return TRUE;                       /* plan a will work */
        !          1007: }
        !          1008: 
        !          1009: /* keep (virtually) nothing in memory */
        !          1010: 
        !          1011: plan_b(filename)
        !          1012: char *filename;
        !          1013: {
        !          1014:     FILE *ifp;
        !          1015:     register int i = 0;
        !          1016:     register int maxlen = 1;
        !          1017:     bool found_revision = (revision == Nullch);
        !          1018: 
        !          1019:     using_plan_a = FALSE;
        !          1020:     if ((ifp = fopen(filename,"r")) == Nullfp)
        !          1021:        fatal("Can't open file %s\n",filename);
        !          1022:     if ((tifd = creat(TMPINNAME,0666)) < 0)
        !          1023:        fatal("Can't open file %s\n",TMPINNAME);
        !          1024:     while (fgets(buf,sizeof buf, ifp) != Nullch) {
        !          1025:        if (revision != Nullch && !found_revision && rev_in_string(buf))
        !          1026:            found_revision = TRUE;
        !          1027:        if ((i = strlen(buf)) > maxlen)
        !          1028:            maxlen = i;                 /* find longest line */
        !          1029:     }
        !          1030:     if (revision != Nullch) {
        !          1031:        if (!found_revision) {
        !          1032:            ask("This file doesn't appear to be the %s version--patch anyway? [n] ",
        !          1033:                revision);
        !          1034:            if (*buf != 'y')
        !          1035:                fatal("Aborted.\n");
        !          1036:        }
        !          1037:        else if (verbose)
        !          1038:            say("Good.  This file appears to be the %s version.\n",
        !          1039:                revision);
        !          1040:     }
        !          1041:     Fseek(ifp,0L,0);           /* rewind file */
        !          1042:     lines_per_buf = BUFFERSIZE / maxlen;
        !          1043:     tireclen = maxlen;
        !          1044:     tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
        !          1045:     tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
        !          1046:     if (tibuf[1] == Nullch)
        !          1047:        fatal("Can't seem to get enough memory.\n");
        !          1048:     for (i=1; ; i++) {
        !          1049:        if (! (i % lines_per_buf))      /* new block */
        !          1050:            if (write(tifd,tibuf[0],BUFFERSIZE) < BUFFERSIZE)
        !          1051:                fatal("patch: can't write temp file.\n");
        !          1052:        if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
        !          1053:          == Nullch) {
        !          1054:            input_lines = i - 1;
        !          1055:            if (i % lines_per_buf)
        !          1056:                if (write(tifd,tibuf[0],BUFFERSIZE) < BUFFERSIZE)
        !          1057:                    fatal("patch: can't write temp file.\n");
        !          1058:            break;
        !          1059:        }
        !          1060:     }
        !          1061:     Fclose(ifp);
        !          1062:     Close(tifd);
        !          1063:     if ((tifd = open(TMPINNAME,0)) < 0) {
        !          1064:        fatal("Can't reopen file %s\n",TMPINNAME);
        !          1065:     }
        !          1066: }
        !          1067: 
        !          1068: /* fetch a line from the input file, \n terminated, not necessarily \0 */
        !          1069: char *
        !          1070: ifetch(line,whichbuf)
        !          1071: register LINENUM line;
        !          1072: int whichbuf;                          /* ignored when file in memory */
        !          1073: {
        !          1074:     if (line < 1 || line > input_lines)
        !          1075:        return "";
        !          1076:     if (using_plan_a)
        !          1077:        return i_ptr[line];
        !          1078:     else {
        !          1079:        LINENUM offline = line % lines_per_buf;
        !          1080:        LINENUM baseline = line - offline;
        !          1081: 
        !          1082:        if (tiline[0] == baseline)
        !          1083:            whichbuf = 0;
        !          1084:        else if (tiline[1] == baseline)
        !          1085:            whichbuf = 1;
        !          1086:        else {
        !          1087:            tiline[whichbuf] = baseline;
        !          1088:            Lseek(tifd,(long)baseline / lines_per_buf * BUFFERSIZE,0);
        !          1089:            if (read(tifd,tibuf[whichbuf],BUFFERSIZE) < 0)
        !          1090:                fatal("Error reading tmp file %s.\n",TMPINNAME);
        !          1091:        }
        !          1092:        return tibuf[whichbuf] + (tireclen*offline);
        !          1093:     }
        !          1094: }
        !          1095: 
        !          1096: /* patch abstract type */
        !          1097: 
        !          1098: static long p_filesize;                        /* size of the patch file */
        !          1099: static LINENUM p_first;                        /* 1st line number */
        !          1100: static LINENUM p_newfirst;             /* 1st line number of replacement */
        !          1101: static LINENUM p_ptrn_lines;           /* # lines in pattern */
        !          1102: static LINENUM p_repl_lines;           /* # lines in replacement text */
        !          1103: static LINENUM p_end = -1;             /* last line in hunk */
        !          1104: static LINENUM p_max;                  /* max allowed value of p_end */
        !          1105: static LINENUM p_context = 3;          /* # of context lines */
        !          1106: static LINENUM p_input_line = 0;       /* current line # from patch file */
        !          1107: static char *p_line[MAXHUNKSIZE];      /* the text of the hunk */
        !          1108: static char p_char[MAXHUNKSIZE];       /* +, -, and ! */
        !          1109: static int p_len[MAXHUNKSIZE];         /* length of each line */
        !          1110: static int p_indent;                   /* indent to patch */
        !          1111: static long p_base;                    /* where to intuit this time */
        !          1112: static long p_start;                   /* where intuit found a patch */
        !          1113: 
        !          1114: re_patch()
        !          1115: {
        !          1116:     p_first = (LINENUM)0;
        !          1117:     p_newfirst = (LINENUM)0;
        !          1118:     p_ptrn_lines = (LINENUM)0;
        !          1119:     p_repl_lines = (LINENUM)0;
        !          1120:     p_end = (LINENUM)-1;
        !          1121:     p_max = (LINENUM)0;
        !          1122:     p_indent = 0;
        !          1123: }
        !          1124: 
        !          1125: open_patch_file(filename)
        !          1126: char *filename;
        !          1127: {
        !          1128:     if (filename == Nullch || !*filename || strEQ(filename,"-")) {
        !          1129:        pfp = fopen(TMPPATNAME,"w");
        !          1130:        if (pfp == Nullfp)
        !          1131:            fatal("patch: can't create %s.\n",TMPPATNAME);
        !          1132:        while (fgets(buf,sizeof buf,stdin) != NULL)
        !          1133:            fputs(buf,pfp);
        !          1134:        Fclose(pfp);
        !          1135:        filename = TMPPATNAME;
        !          1136:     }
        !          1137:     pfp = fopen(filename,"r");
        !          1138:     if (pfp == Nullfp)
        !          1139:        fatal("patch file %s not found\n",filename);
        !          1140:     Fstat(fileno(pfp), &filestat);
        !          1141:     p_filesize = filestat.st_size;
        !          1142:     next_intuit_at(0L);                        /* start at the beginning */
        !          1143: }
        !          1144: 
        !          1145: bool
        !          1146: there_is_another_patch()
        !          1147: {
        !          1148:     bool no_input_file = (filearg[0] == Nullch);
        !          1149:     
        !          1150:     if (p_base != 0L && p_base >= p_filesize) {
        !          1151:        if (verbose)
        !          1152:            say("done\n");
        !          1153:        return FALSE;
        !          1154:     }
        !          1155:     if (verbose)
        !          1156:        say("Hmm...");
        !          1157:     diff_type = intuit_diff_type();
        !          1158:     if (!diff_type) {
        !          1159:        if (p_base != 0L) {
        !          1160:            if (verbose)
        !          1161:                say("  Ignoring the trailing garbage.\ndone\n");
        !          1162:        }
        !          1163:        else
        !          1164:            say("  I can't seem to find a patch in there anywhere.\n");
        !          1165:        return FALSE;
        !          1166:     }
        !          1167:     if (verbose)
        !          1168:        say("  %sooks like %s to me...\n",
        !          1169:            (p_base == 0L ? "L" : "The next patch l"),
        !          1170:            diff_type == CONTEXT_DIFF ? "a context diff" :
        !          1171:            diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
        !          1172:            diff_type == NORMAL_DIFF ? "a normal diff" :
        !          1173:            "an ed script" );
        !          1174:     if (p_indent && verbose)
        !          1175:        say("(Patch is indented %d space%s.)\n",p_indent,p_indent==1?"":"s");
        !          1176:     skip_to(p_start);
        !          1177:     if (no_input_file) {
        !          1178:        if (filearg[0] == Nullch) {
        !          1179:            ask("File to patch: ");
        !          1180:            filearg[0] = fetchname(buf);
        !          1181:        }
        !          1182:        else if (verbose) {
        !          1183:            say("Patching file %s...\n",filearg[0]);
        !          1184:        }
        !          1185:     }
        !          1186:     return TRUE;
        !          1187: }
        !          1188: 
        !          1189: intuit_diff_type()
        !          1190: {
        !          1191:     long this_line = 0;
        !          1192:     long previous_line;
        !          1193:     long first_command_line = -1;
        !          1194:     bool last_line_was_command = FALSE;
        !          1195:     bool this_line_is_command = FALSE;
        !          1196:     bool last_line_was_stars = FALSE;
        !          1197:     bool this_line_is_stars = FALSE;
        !          1198:     register int indent;
        !          1199:     register char *s, *t;
        !          1200:     char *oldname = Nullch;
        !          1201:     char *newname = Nullch;
        !          1202:     bool no_filearg = (filearg[0] == Nullch);
        !          1203: 
        !          1204:     Fseek(pfp,p_base,0);
        !          1205:     for (;;) {
        !          1206:        previous_line = this_line;
        !          1207:        last_line_was_command = this_line_is_command;
        !          1208:        last_line_was_stars = this_line_is_stars;
        !          1209:        this_line = ftell(pfp);
        !          1210:        indent = 0;
        !          1211:        if (fgets(buf,sizeof buf,pfp) == Nullch) {
        !          1212:            if (first_command_line >= 0L) {
        !          1213:                                        /* nothing but deletes!? */
        !          1214:                p_start = first_command_line;
        !          1215:                return ED_DIFF;
        !          1216:            }
        !          1217:            else {
        !          1218:                p_start = this_line;
        !          1219:                return 0;
        !          1220:            }
        !          1221:        }
        !          1222:        for (s = buf; *s == ' ' || *s == '\t'; s++) {
        !          1223:            if (*s == '\t')
        !          1224:                indent += 8 - (indent % 8);
        !          1225:            else
        !          1226:                indent++;
        !          1227:        }
        !          1228:        for (t=s; isdigit(*t) || *t == ','; t++) ; 
        !          1229:        this_line_is_command = (isdigit(*s) &&
        !          1230:          (*t == 'd' || *t == 'c' || *t == 'a') );
        !          1231:        if (first_command_line < 0L && this_line_is_command) { 
        !          1232:            first_command_line = this_line;
        !          1233:            p_indent = indent;          /* assume this for now */
        !          1234:        }
        !          1235:        if (strnEQ(s,"*** ",4))
        !          1236:            oldname = fetchname(s+4);
        !          1237:        else if (strnEQ(s,"--- ",4)) {
        !          1238:            newname = fetchname(s+4);
        !          1239:            if (no_filearg) {
        !          1240:                if (oldname && newname) {
        !          1241:                    if (strlen(oldname) < strlen(newname))
        !          1242:                        filearg[0] = oldname;
        !          1243:                    else
        !          1244:                        filearg[0] = newname;
        !          1245:                }
        !          1246:                else if (oldname)
        !          1247:                    filearg[0] = oldname;
        !          1248:                else if (newname)
        !          1249:                    filearg[0] = newname;
        !          1250:            }
        !          1251:        }
        !          1252:        else if (strnEQ(s,"Index:",6)) {
        !          1253:            if (no_filearg) 
        !          1254:                filearg[0] = fetchname(s+6);
        !          1255:                                        /* this filearg might get limboed */
        !          1256:        }
        !          1257:        else if (strnEQ(s,"Prereq:",7)) {
        !          1258:            for (t=s+7; isspace(*t); t++) ;
        !          1259:            revision = savestr(t);
        !          1260:            for (t=revision; *t && !isspace(*t); t++) ;
        !          1261:            *t = '\0';
        !          1262:            if (!*revision) {
        !          1263:                free(revision);
        !          1264:                revision = Nullch;
        !          1265:            }
        !          1266:        }
        !          1267:        if ((!diff_type || diff_type == ED_DIFF) &&
        !          1268:          first_command_line >= 0L &&
        !          1269:          strEQ(s,".\n") ) {
        !          1270:            p_indent = indent;
        !          1271:            p_start = first_command_line;
        !          1272:            return ED_DIFF;
        !          1273:        }
        !          1274:        this_line_is_stars = strnEQ(s,"********",8);
        !          1275:        if ((!diff_type || diff_type == CONTEXT_DIFF) && last_line_was_stars &&
        !          1276:                 strnEQ(s,"*** ",4)) {
        !          1277:            /* if this is a new context diff the character just before */
        !          1278:            /* the newline is a '*'. */
        !          1279:            while (*s != '\n')
        !          1280:                s++;
        !          1281:            p_indent = indent;
        !          1282:            p_start = previous_line;
        !          1283:            return (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
        !          1284:        }
        !          1285:        if ((!diff_type || diff_type == NORMAL_DIFF) && 
        !          1286:          last_line_was_command &&
        !          1287:          (strnEQ(s,"< ",2) || strnEQ(s,"> ",2)) ) {
        !          1288:            p_start = previous_line;
        !          1289:            p_indent = indent;
        !          1290:            return NORMAL_DIFF;
        !          1291:        }
        !          1292:     }
        !          1293: }
        !          1294: 
        !          1295: char *
        !          1296: fetchname(at)
        !          1297: char *at;
        !          1298: {
        !          1299:     char *s = savestr(at);
        !          1300:     char *name;
        !          1301:     register char *t;
        !          1302:     char tmpbuf[200];
        !          1303: 
        !          1304:     for (t=s; isspace(*t); t++) ;
        !          1305:     name = t;
        !          1306:     for (; *t && !isspace(*t); t++)
        !          1307:        if (!usepath)
        !          1308:            if (*t == '/')
        !          1309:                name = t+1;
        !          1310:     *t = '\0';
        !          1311:     name = savestr(name);
        !          1312:     Sprintf(tmpbuf,"RCS/%s",name);
        !          1313:     free(s);
        !          1314:     if (stat(name,&filestat) < 0) {
        !          1315:        Strcat(tmpbuf,RCSSUFFIX);
        !          1316:        if (stat(tmpbuf,&filestat) < 0 && stat(tmpbuf+4,&filestat) < 0) {
        !          1317:            Sprintf(tmpbuf,"SCCS/%s%s",SCCSPREFIX,name);
        !          1318:            if (stat(tmpbuf,&filestat) < 0 && stat(tmpbuf+5,&filestat) < 0) {
        !          1319:                free(name);
        !          1320:                name = Nullch;
        !          1321:            }
        !          1322:        }
        !          1323:     }
        !          1324:     return name;
        !          1325: }
        !          1326: 
        !          1327: next_intuit_at(file_pos)
        !          1328: long file_pos;
        !          1329: {
        !          1330:     p_base = file_pos;
        !          1331: }
        !          1332: 
        !          1333: skip_to(file_pos)
        !          1334: long file_pos;
        !          1335: {
        !          1336:     char *ret;
        !          1337: 
        !          1338:     assert(p_base <= file_pos);
        !          1339:     if (verbose && p_base < file_pos) {
        !          1340:        Fseek(pfp,p_base,0);
        !          1341:        say("The text leading up to this was:\n--------------------------\n");
        !          1342:        while (ftell(pfp) < file_pos) {
        !          1343:            ret = fgets(buf,sizeof buf,pfp);
        !          1344:            assert(ret != Nullch);
        !          1345:            say("|%s",buf);
        !          1346:        }
        !          1347:        say("--------------------------\n");
        !          1348:     }
        !          1349:     else
        !          1350:        Fseek(pfp,file_pos,0);
        !          1351: }
        !          1352: 
        !          1353: bool
        !          1354: another_hunk()
        !          1355: {
        !          1356:     register char *s;
        !          1357:     char *ret;
        !          1358:     register int context = 0;
        !          1359: 
        !          1360:     while (p_end >= 0) {
        !          1361:        free(p_line[p_end--]);
        !          1362:     }
        !          1363:     assert(p_end == -1);
        !          1364: 
        !          1365:     p_max = MAXHUNKSIZE;               /* gets reduced when --- found */
        !          1366:     if (diff_type == CONTEXT_DIFF) {
        !          1367:        long line_beginning = ftell(pfp);
        !          1368:        LINENUM repl_beginning = 0;
        !          1369: 
        !          1370:        ret = pgets(buf,sizeof buf, pfp);
        !          1371:        if (ret == Nullch || strnNE(buf,"********",8)) {
        !          1372:            next_intuit_at(line_beginning);
        !          1373:            return FALSE;
        !          1374:        }
        !          1375:        p_context = 100;
        !          1376:        while (p_end < p_max) {
        !          1377:            ret = pgets(buf,sizeof buf, pfp);
        !          1378:            if (ret == Nullch) {
        !          1379:                if (p_max - p_end < 4)
        !          1380:                    Strcpy(buf,"  \n"); /* assume blank lines got chopped */
        !          1381:                else
        !          1382:                    fatal("Unexpected end of file in patch.\n");
        !          1383:            }
        !          1384:            p_input_line++;
        !          1385:            if (strnEQ(buf,"********",8))
        !          1386:                fatal("Unexpected end of hunk at line %d.\n",
        !          1387:                    p_input_line);
        !          1388:            p_char[++p_end] = *buf;
        !          1389:            switch (*buf) {
        !          1390:            case '*':
        !          1391:                if (p_end != 0)
        !          1392:                    fatal("Unexpected *** at line %d: %s", p_input_line, buf);
        !          1393:                context = 0;
        !          1394:                p_line[p_end] = savestr(buf);
        !          1395:                for (s=buf; *s && !isdigit(*s); s++) ;
        !          1396:                p_first = (LINENUM) atol(s);
        !          1397:                while (isdigit(*s)) s++;
        !          1398:                for (; *s && !isdigit(*s); s++) ;
        !          1399:                p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
        !          1400:                break;
        !          1401:            case '-':
        !          1402:                if (buf[1] == '-') {
        !          1403:                    if (p_end != p_ptrn_lines + 1 &&
        !          1404:                        p_end != p_ptrn_lines + 2)
        !          1405:                        fatal("Unexpected --- at line %d: %s",
        !          1406:                            p_input_line,buf);
        !          1407:                    repl_beginning = p_end;
        !          1408:                    context = 0;
        !          1409:                    p_line[p_end] = savestr(buf);
        !          1410:                    p_char[p_end] = '=';
        !          1411:                    for (s=buf; *s && !isdigit(*s); s++) ;
        !          1412:                    p_newfirst = (LINENUM) atol(s);
        !          1413:                    while (isdigit(*s)) s++;
        !          1414:                    for (; *s && !isdigit(*s); s++) ;
        !          1415:                    p_max = ((LINENUM)atol(s)) - p_newfirst + 1 + p_end;
        !          1416:                    break;
        !          1417:                }
        !          1418:                /* FALL THROUGH */
        !          1419:            case '+': case '!':
        !          1420:                if (context > 0) {
        !          1421:                    if (context < p_context)
        !          1422:                        p_context = context;
        !          1423:                    context = -100;
        !          1424:                }
        !          1425:                p_line[p_end] = savestr(buf+2);
        !          1426:                break;
        !          1427:            case '\t': case '\n':       /* assume the 2 spaces got eaten */
        !          1428:                p_line[p_end] = savestr(buf);
        !          1429:                if (p_end != p_ptrn_lines + 1) {
        !          1430:                    context++;
        !          1431:                    p_char[p_end] = ' ';
        !          1432:                }
        !          1433:                break;
        !          1434:            case ' ':
        !          1435:                context++;
        !          1436:                p_line[p_end] = savestr(buf+2);
        !          1437:                break;
        !          1438:            default:
        !          1439:                fatal("Malformed patch at line %d: %s",p_input_line,buf);
        !          1440:            }
        !          1441:            p_len[p_end] = 0;
        !          1442:            if (p_line[p_end] != 0)
        !          1443:                p_len[p_end] = strlen(p_line[p_end]);
        !          1444:                                        /* for strncmp() so we do not have */
        !          1445:                                        /* to assume null termination */
        !          1446:        }
        !          1447:        if (p_end >=0 && !p_ptrn_lines)
        !          1448:            fatal("No --- found in patch at line %d\n", pch_hunk_beg());
        !          1449:        p_repl_lines = p_end - repl_beginning;
        !          1450:     }
        !          1451:     else if (diff_type == NEW_CONTEXT_DIFF) {
        !          1452:        long line_beginning = ftell(pfp);
        !          1453:        LINENUM repl_beginning = 0;
        !          1454:        LINENUM fillcnt = 0;
        !          1455:        LINENUM fillsrc;
        !          1456:        LINENUM filldst;
        !          1457: 
        !          1458:        ret = pgets(buf,sizeof buf, pfp);
        !          1459:        if (ret == Nullch || strnNE(buf,"********",8)) {
        !          1460:            next_intuit_at(line_beginning);
        !          1461:            return FALSE;
        !          1462:        }
        !          1463:        p_context = 0;
        !          1464:        while (p_end < p_max) {
        !          1465:            line_beginning = ftell(pfp);
        !          1466:            ret = pgets(buf,sizeof buf, pfp);
        !          1467:            if (ret == Nullch) {
        !          1468:                if (p_max - p_end < 4)
        !          1469:                    Strcpy(buf,"  \n"); /* assume blank lines got chopped */
        !          1470:                else
        !          1471:                    fatal("Unexpected end of file in patch.\n");
        !          1472:            }
        !          1473:            p_input_line++;
        !          1474:            p_char[++p_end] = *buf;
        !          1475:            switch (*buf) {
        !          1476:            case '*':
        !          1477:                if (strnEQ(buf,"********",8)) {
        !          1478:                    if (p_end != repl_beginning + 1)
        !          1479:                        fatal("Unexpected end of hunk at line %d.\n",
        !          1480:                                p_input_line);
        !          1481:                    /* redundant 'new' context lines were omitted - set up */
        !          1482:                    /* to fill them in from the the old file's context */
        !          1483:                    fillsrc = 1;
        !          1484:                    filldst = p_end;
        !          1485:                    fillcnt = p_max - repl_beginning;
        !          1486:                    p_end = p_max;
        !          1487:                    Fseek(pfp, line_beginning, 0); /* backup the diff input */
        !          1488:                    break;
        !          1489:                }
        !          1490:                if (p_end != 0)
        !          1491:                    fatal("Unexpected *** at line %d: %s", p_input_line, buf);
        !          1492:                context = 0;
        !          1493:                p_line[p_end] = savestr(buf);
        !          1494:                for (s=buf; *s && !isdigit(*s); s++) ;
        !          1495:                p_first = (LINENUM) atol(s);
        !          1496:                while (isdigit(*s)) s++;
        !          1497:                for (; *s && !isdigit(*s); s++) ;
        !          1498:                p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
        !          1499:                break;
        !          1500:            case '-':
        !          1501:                if (buf[1] == '-') {
        !          1502:                    if (p_end != p_ptrn_lines + 1) {
        !          1503:                        if (p_end == 1) {
        !          1504:                            /* `old' lines were omitted - set up to fill them */
        !          1505:                            /* in from 'new' context lines. */
        !          1506:                            p_end = p_ptrn_lines + 1;
        !          1507:                            fillsrc = p_end + 1;
        !          1508:                            filldst = 1;
        !          1509:                            fillcnt = p_ptrn_lines;
        !          1510:                        } else
        !          1511:                            fatal("Unexpected --- at line %d: %s",
        !          1512:                                p_input_line,buf);
        !          1513:                    }
        !          1514:                    repl_beginning = p_end;
        !          1515:                    p_line[p_end] = savestr(buf);
        !          1516:                    p_char[p_end] = '=';
        !          1517:                    for (s=buf; *s && !isdigit(*s); s++) ;
        !          1518:                    p_newfirst = (LINENUM) atol(s);
        !          1519:                    while (isdigit(*s)) s++;
        !          1520:                    for (; *s && !isdigit(*s); s++) ;
        !          1521:                    p_max = ((LINENUM)atol(s)) - p_newfirst + 1 + p_end;
        !          1522:                    break;
        !          1523:                }
        !          1524:                /* FALL THROUGH */
        !          1525:            case '+': case '!':
        !          1526:                if (context > 0 && p_context == 0) {
        !          1527:                    p_context = context;
        !          1528:                }
        !          1529:                p_line[p_end] = savestr(buf+2);
        !          1530:                break;
        !          1531:            case '\t': case '\n':       /* assume the 2 spaces got eaten */
        !          1532:                p_line[p_end] = savestr(buf);
        !          1533:                if (p_end != p_ptrn_lines + 1) {
        !          1534:                    context++;
        !          1535:                    p_char[p_end] = ' ';
        !          1536:                }
        !          1537:                break;
        !          1538:            case ' ':
        !          1539:                context++;
        !          1540:                p_line[p_end] = savestr(buf+2);
        !          1541:                break;
        !          1542:            default:
        !          1543:                fatal("Malformed patch at line %d: %s",p_input_line,buf);
        !          1544:            }
        !          1545:            p_len[p_end] = 0;
        !          1546:            if (p_line[p_end] != 0)
        !          1547:                p_len[p_end] = strlen(p_line[p_end]);
        !          1548:                                        /* for strncmp() so we do not have */
        !          1549:                                        /* to assume null termination */
        !          1550:        }
        !          1551:        if (p_end >=0 && !p_ptrn_lines)
        !          1552:            fatal("No --- found in patch at line %d\n", pch_hunk_beg());
        !          1553: 
        !          1554:        /* if there were omitted context lines, fill them in */
        !          1555:        if (fillcnt) {
        !          1556:            while (fillcnt-- > 0) {
        !          1557:                while (p_char[fillsrc] != ' ')
        !          1558:                    fillsrc++;
        !          1559:                p_line[filldst] = p_line[fillsrc];
        !          1560:                p_char[filldst] = p_char[fillsrc];
        !          1561:                p_len[filldst] = p_len[fillsrc];
        !          1562:                fillsrc++; filldst++;
        !          1563:            }
        !          1564:            assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
        !          1565:            assert(filldst==p_end+1 || filldst==repl_beginning);
        !          1566:        }
        !          1567:        p_repl_lines = p_end - repl_beginning;
        !          1568:     }
        !          1569:     else {                             /* normal diff--fake it up */
        !          1570:        char hunk_type;
        !          1571:        register int i;
        !          1572:        LINENUM min, max;
        !          1573:        long line_beginning = ftell(pfp);
        !          1574: 
        !          1575:        p_context = 0;
        !          1576:        ret = pgets(buf,sizeof buf, pfp);
        !          1577:        p_input_line++;
        !          1578:        if (ret == Nullch || !isdigit(*buf)) {
        !          1579:            next_intuit_at(line_beginning);
        !          1580:            return FALSE;
        !          1581:        }
        !          1582:        p_first = (LINENUM)atol(buf);
        !          1583:        for (s=buf; isdigit(*s); s++) ;
        !          1584:        if (*s == ',') {
        !          1585:            p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
        !          1586:            while (isdigit(*s)) s++;
        !          1587:        }
        !          1588:        else
        !          1589:            p_ptrn_lines = (*s != 'a');
        !          1590:        hunk_type = *s;
        !          1591:        if (hunk_type == 'a')
        !          1592:            p_first++;                  /* do append rather than insert */
        !          1593:        min = (LINENUM)atol(++s);
        !          1594:        for (; isdigit(*s); s++) ;
        !          1595:        if (*s == ',')
        !          1596:            max = (LINENUM)atol(++s);
        !          1597:        else
        !          1598:            max = min;
        !          1599:        if (hunk_type == 'd')
        !          1600:            min++;
        !          1601:        p_end = p_ptrn_lines + 1 + max - min + 1;
        !          1602:        p_newfirst = min;
        !          1603:        p_repl_lines = max - min + 1;
        !          1604:        Sprintf(buf,"*** %d,%d\n", p_first, p_first + p_ptrn_lines - 1);
        !          1605:        p_line[0] = savestr(buf);
        !          1606:        p_char[0] = '*';
        !          1607:        for (i=1; i<=p_ptrn_lines; i++) {
        !          1608:            ret = pgets(buf,sizeof buf, pfp);
        !          1609:            p_input_line++;
        !          1610:            if (ret == Nullch)
        !          1611:                fatal("Unexpected end of file in patch at line %d.\n",
        !          1612:                  p_input_line);
        !          1613:            if (*buf != '<')
        !          1614:                fatal("< expected at line %d of patch.\n", p_input_line);
        !          1615:            p_line[i] = savestr(buf+2);
        !          1616:            p_len[i] = 0;
        !          1617:            if (p_line[i] != 0)
        !          1618:                p_len[i] = strlen(p_line[i]);
        !          1619:            p_char[i] = '-';
        !          1620:        }
        !          1621:        if (hunk_type == 'c') {
        !          1622:            ret = pgets(buf,sizeof buf, pfp);
        !          1623:            p_input_line++;
        !          1624:            if (ret == Nullch)
        !          1625:                fatal("Unexpected end of file in patch at line %d.\n",
        !          1626:                    p_input_line);
        !          1627:            if (*buf != '-')
        !          1628:                fatal("--- expected at line %d of patch.\n", p_input_line);
        !          1629:        }
        !          1630:        Sprintf(buf,"--- %d,%d\n",min,max);
        !          1631:        p_line[i] = savestr(buf);
        !          1632:        p_char[i] = '=';
        !          1633:        for (i++; i<=p_end; i++) {
        !          1634:            ret = pgets(buf,sizeof buf, pfp);
        !          1635:            p_input_line++;
        !          1636:            if (ret == Nullch)
        !          1637:                fatal("Unexpected end of file in patch at line %d.\n",
        !          1638:                    p_input_line);
        !          1639:            if (*buf != '>')
        !          1640:                fatal("> expected at line %d of patch.\n", p_input_line);
        !          1641:            p_line[i] = savestr(buf+2);
        !          1642:            p_len[i] = 0;
        !          1643:            if (p_line[i] != 0)
        !          1644:                p_len[i] = strlen(p_line[i]);
        !          1645:            p_char[i] = '+';
        !          1646:        }
        !          1647:     }
        !          1648:     if (reverse)                       /* backwards patch? */
        !          1649:        pch_swap();
        !          1650: #ifdef DEBUGGING
        !          1651:     if (debug & 2) {
        !          1652:        int i;
        !          1653:        char special;
        !          1654: 
        !          1655:        for (i=0; i <= p_end; i++) {
        !          1656:            if (i == p_ptrn_lines)
        !          1657:                special = '^';
        !          1658:            else
        !          1659:                special = ' ';
        !          1660:            printf("%3d %c %c %s",i,p_char[i],special,p_line[i]);
        !          1661:        }
        !          1662:     }
        !          1663: #endif
        !          1664:     return TRUE;
        !          1665: }
        !          1666: 
        !          1667: char *
        !          1668: pgets(bf,sz,fp)
        !          1669: char *bf;
        !          1670: int sz;
        !          1671: FILE *fp;
        !          1672: {
        !          1673:     char *ret = fgets(bf,sz,fp);
        !          1674:     register char *s;
        !          1675:     register int indent = 0;
        !          1676: 
        !          1677:     if (p_indent && ret != Nullch) {
        !          1678:        for (s=buf; indent < p_indent && (*s == ' ' || *s == '\t'); s++) {
        !          1679:            if (*s == '\t')
        !          1680:                indent += 8 - (indent % 7);
        !          1681:            else
        !          1682:                indent++;
        !          1683:        }
        !          1684:        if (buf != s)
        !          1685:            Strcpy(buf,s);
        !          1686:     }
        !          1687:     return ret;
        !          1688: }
        !          1689: 
        !          1690: pch_swap()
        !          1691: {
        !          1692:     char *tp_line[MAXHUNKSIZE];                /* the text of the hunk */
        !          1693:     char tp_char[MAXHUNKSIZE];         /* +, -, and ! */
        !          1694:     int tp_len[MAXHUNKSIZE];           /* length of each line */
        !          1695:     register LINENUM i, n;
        !          1696:     bool blankline = FALSE;
        !          1697:     register char *s;
        !          1698: 
        !          1699:     i = p_first;
        !          1700:     p_first = p_newfirst;
        !          1701:     p_newfirst = i;
        !          1702:     
        !          1703:     /* make a scratch copy */
        !          1704: 
        !          1705:     for (i=0; i<=p_end; i++) {
        !          1706:        tp_line[i] = p_line[i];
        !          1707:        tp_char[i] = p_char[i];
        !          1708:        tp_len[i] = p_len[i];
        !          1709:     }
        !          1710: 
        !          1711:     /* now turn the new into the old */
        !          1712: 
        !          1713:     i = p_ptrn_lines + 1;
        !          1714:     if (tp_char[i] == '\n') {          /* account for possible blank line */
        !          1715:        blankline = TRUE;
        !          1716:        i++;
        !          1717:     }
        !          1718:     for (n=0; i <= p_end; i++,n++) {
        !          1719:        p_line[n] = tp_line[i];
        !          1720:        p_char[n] = tp_char[i];
        !          1721:        if (p_char[n] == '+')
        !          1722:            p_char[n] = '-';
        !          1723:        p_len[n] = tp_len[i];
        !          1724:     }
        !          1725:     if (blankline) {
        !          1726:        i = p_ptrn_lines + 1;
        !          1727:        p_line[n] = tp_line[i];
        !          1728:        p_char[n] = tp_char[i];
        !          1729:        p_len[n] = tp_len[i];
        !          1730:        n++;
        !          1731:     }
        !          1732:     assert(p_char[0] == '=');
        !          1733:     p_char[0] = '*';
        !          1734:     for (s=p_line[0]; *s; s++)
        !          1735:        if (*s == '-')
        !          1736:            *s = '*';
        !          1737: 
        !          1738:     /* now turn the old into the new */
        !          1739: 
        !          1740:     assert(tp_char[0] == '*');
        !          1741:     tp_char[0] = '=';
        !          1742:     for (s=tp_line[0]; *s; s++)
        !          1743:        if (*s == '*')
        !          1744:            *s = '-';
        !          1745:     for (i=0; n <= p_end; i++,n++) {
        !          1746:        p_line[n] = tp_line[i];
        !          1747:        p_char[n] = tp_char[i];
        !          1748:        if (p_char[n] == '-')
        !          1749:            p_char[n] = '+';
        !          1750:        p_len[n] = tp_len[i];
        !          1751:     }
        !          1752:     assert(i == p_ptrn_lines + 1);
        !          1753:     i = p_ptrn_lines;
        !          1754:     p_ptrn_lines = p_repl_lines;
        !          1755:     p_repl_lines = i;
        !          1756: }
        !          1757: 
        !          1758: LINENUM
        !          1759: pch_first()
        !          1760: {
        !          1761:     return p_first;
        !          1762: }
        !          1763: 
        !          1764: LINENUM
        !          1765: pch_ptrn_lines()
        !          1766: {
        !          1767:     return p_ptrn_lines;
        !          1768: }
        !          1769: 
        !          1770: LINENUM
        !          1771: pch_newfirst()
        !          1772: {
        !          1773:     return p_newfirst;
        !          1774: }
        !          1775: 
        !          1776: LINENUM
        !          1777: pch_repl_lines()
        !          1778: {
        !          1779:     return p_repl_lines;
        !          1780: }
        !          1781: 
        !          1782: LINENUM
        !          1783: pch_end()
        !          1784: {
        !          1785:     return p_end;
        !          1786: }
        !          1787: 
        !          1788: LINENUM
        !          1789: pch_context()
        !          1790: {
        !          1791:     return p_context;
        !          1792: }
        !          1793: 
        !          1794: pch_line_len(line)
        !          1795: LINENUM line;
        !          1796: {
        !          1797:     return p_len[line];
        !          1798: }
        !          1799: 
        !          1800: char
        !          1801: pch_char(line)
        !          1802: LINENUM line;
        !          1803: {
        !          1804:     return p_char[line];
        !          1805: }
        !          1806: 
        !          1807: char *
        !          1808: pfetch(line)
        !          1809: LINENUM line;
        !          1810: {
        !          1811:     return p_line[line];
        !          1812: }
        !          1813: 
        !          1814: LINENUM
        !          1815: pch_hunk_beg()
        !          1816: {
        !          1817:     return p_input_line - p_end - 1;
        !          1818: }
        !          1819: 
        !          1820: char *
        !          1821: savestr(s)
        !          1822: register char *s;
        !          1823: {
        !          1824:     register char  *rv,
        !          1825:                    *t;
        !          1826: 
        !          1827:     t = s;
        !          1828:     while (*t++);
        !          1829:     rv = malloc((MEM) (t - s));
        !          1830:     if (rv == NULL)
        !          1831:        fatal ("patch: out of memory (savestr)\n");
        !          1832:     t = rv;
        !          1833:     while (*t++ = *s++);
        !          1834:     return rv;
        !          1835: }
        !          1836: 
        !          1837: my_exit(status)
        !          1838: int status;
        !          1839: {
        !          1840:     Unlink(TMPINNAME);
        !          1841:     Unlink(TMPOUTNAME);
        !          1842:     Unlink(TMPREJNAME);
        !          1843:     Unlink(TMPPATNAME);
        !          1844:     exit(status);
        !          1845: }
        !          1846: 
        !          1847: #ifdef lint
        !          1848: 
        !          1849: /*VARARGS ARGSUSED*/
        !          1850: say(pat) char *pat; { ; }
        !          1851: /*VARARGS ARGSUSED*/
        !          1852: fatal(pat) char *pat; { ; }
        !          1853: /*VARARGS ARGSUSED*/
        !          1854: ask(pat) char *pat; { ; }
        !          1855: 
        !          1856: #else lint
        !          1857: 
        !          1858: say(pat,arg1,arg2,arg3)
        !          1859: char *pat;
        !          1860: int arg1,arg2,arg3;
        !          1861: {
        !          1862:     fprintf(stderr,pat,arg1,arg2,arg3);
        !          1863:     Fflush(stderr);
        !          1864: }
        !          1865: 
        !          1866: fatal(pat,arg1,arg2,arg3)
        !          1867: char *pat;
        !          1868: int arg1,arg2,arg3;
        !          1869: {
        !          1870:     say(pat,arg1,arg2,arg3);
        !          1871:     my_exit(1);
        !          1872: }
        !          1873: 
        !          1874: ask(pat,arg1,arg2,arg3)
        !          1875: char *pat;
        !          1876: int arg1,arg2,arg3;
        !          1877: {
        !          1878:     int ttyfd = open("/dev/tty",2);
        !          1879:     int r;
        !          1880: 
        !          1881:     say(pat,arg1,arg2,arg3);
        !          1882:     if (ttyfd >= 0) {
        !          1883:        r = read(ttyfd, buf, sizeof buf);
        !          1884:        Close(ttyfd);
        !          1885:     }
        !          1886:     else
        !          1887:        r = read(2, buf, sizeof buf);
        !          1888:     if (r <= 0)
        !          1889:        buf[0] = 0;
        !          1890: }
        !          1891: #endif lint
        !          1892: 
        !          1893: bool
        !          1894: rev_in_string(string)
        !          1895: char *string;
        !          1896: {
        !          1897:     register char *s;
        !          1898:     register int patlen;
        !          1899: 
        !          1900:     if (revision == Nullch)
        !          1901:        return TRUE;
        !          1902:     patlen = strlen(revision);
        !          1903:     for (s = string; *s; s++) {
        !          1904:        if (isspace(*s) && strnEQ(s+1,revision,patlen) && 
        !          1905:                isspace(s[patlen+1] )) {
        !          1906:            return TRUE;
        !          1907:        }
        !          1908:     }
        !          1909:     return FALSE;
        !          1910: }
        !          1911: 
        !          1912: set_signals()
        !          1913: {
        !          1914:     /*NOSTRICT*/
        !          1915:     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        !          1916:        Signal(SIGHUP, my_exit);
        !          1917:     /*NOSTRICT*/
        !          1918:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
        !          1919:        Signal(SIGINT, my_exit);
        !          1920: }
        !          1921: 
        !          1922: ignore_signals()
        !          1923: {
        !          1924:     /*NOSTRICT*/
        !          1925:     Signal(SIGHUP, SIG_IGN);
        !          1926:     /*NOSTRICT*/
        !          1927:     Signal(SIGINT, SIG_IGN);
        !          1928: }

unix.superglobalmegacorp.com

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