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