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