# 2.11BSD#431 - /usr/src/usr.bin/patch/pch.c

##### Functions

    another_hunk      X
    do_ed_script      X
    grow_hunkmax      X
    intuit_diff_type  X
    next_intuit_at    X
    open_patch_file   X
    pch_char          X
    pch_context       X
    pch_end           X
    pch_first         X
    pch_hunk_beg      X
    pch_line_len      X
    pch_newfirst      X
    pch_ptrn_lines    X
    pch_repl_lines    X
    pch_swap          X
    pfetch            X
    pgets             X
    re_patch          X
    set_hunkmax       X
    skip_to           X
    there_is_another_patchX

       1: /* $Header: pch.c,v 2.0.1.7 88/06/03 15:13:28 lwall Locked $
       2:  *
       3:  * $Log:	pch.c,v $
       4:  * Revision 2.0.1.7  88/06/03  15:13:28  lwall
       5:  * patch10: Can now find patches in shar scripts.
       6:  * patch10: Hunks that swapped and then swapped back could core dump.
       7:  *
       8:  * Revision 2.0.1.6  87/06/04  16:18:13  lwall
       9:  * pch_swap didn't swap p_bfake and p_efake.
      10:  *
      11:  * Revision 2.0.1.5  87/01/30  22:47:42  lwall
      12:  * Improved responses to mangled patches.
      13:  *
      14:  * Revision 2.0.1.4  87/01/05  16:59:53  lwall
      15:  * New-style context diffs caused double call to free().
      16:  *
      17:  * Revision 2.0.1.3  86/11/14  10:08:33  lwall
      18:  * Fixed problem where a long pattern wouldn't grow the hunk.
      19:  * Also restored p_input_line when backtracking so error messages are right.
      20:  *
      21:  * Revision 2.0.1.2  86/11/03  17:49:52  lwall
      22:  * New-style delete triggers spurious assertion error.
      23:  *
      24:  * Revision 2.0.1.1  86/10/29  15:52:08  lwall
      25:  * Could falsely report new-style context diff.
      26:  *
      27:  * Revision 2.0  86/09/17  15:39:37  lwall
      28:  * Baseline for netwide release.
      29:  *
      30:  */
      31:
      32: #include "EXTERN.h"
      33: #include "common.h"
      34: #include "util.h"
      35: #include "INTERN.h"
      36: #include "pch.h"
      37:
      38: /* Patch (diff listing) abstract type. */
      39:
      40: static long p_filesize;         /* size of the patch file */
      41: static LINENUM p_first;         /* 1st line number */
      42: static LINENUM p_newfirst;      /* 1st line number of replacement */
      43: static LINENUM p_ptrn_lines;        /* # lines in pattern */
      44: static LINENUM p_repl_lines;        /* # lines in replacement text */
      45: static LINENUM p_end = -1;      /* last line in hunk */
      46: static LINENUM p_max;           /* max allowed value of p_end */
      47: static LINENUM p_context = 3;       /* # of context lines */
      48: static LINENUM p_input_line = 0;    /* current line # from patch file */
      49: static char **p_line = Null(char**);    /* the text of the hunk */
      50: static short *p_len = Null(short*); /* length of each line */
      51: static char *p_char = Nullch;       /* +, -, and ! */
      52: static int hunkmax = INITHUNKMAX;   /* size of above arrays to begin with */
      53: static int p_indent;            /* indent to patch */
      54: static LINENUM p_base;          /* where to intuit this time */
      55: static LINENUM p_bline;         /* line # of p_base */
      56: static LINENUM p_start;         /* where intuit found a patch */
      57: static LINENUM p_sline;         /* and the line number for it */
      58: static LINENUM p_hunk_beg;      /* line number of current hunk */
      59: static LINENUM p_efake = -1;        /* end of faked up lines--don't free */
      60: static LINENUM p_bfake = -1;        /* beg of faked up lines */
      61:
      62: /* Prepare to look for the next patch in the patch file. */
      63:
      64: void
      65: re_patch()
      66: {
      67:     p_first = Nulline;
      68:     p_newfirst = Nulline;
      69:     p_ptrn_lines = Nulline;
      70:     p_repl_lines = Nulline;
      71:     p_end = (LINENUM)-1;
      72:     p_max = Nulline;
      73:     p_indent = 0;
      74: }
      75:
      76: /* Open the patch file at the beginning of time. */
      77:
      78: void
      79: open_patch_file(filename)
      80: char *filename;
      81: {
      82:     if (filename == Nullch || !*filename || strEQ(filename, "-")) {
      83:     pfp = fopen(TMPPATNAME, "w");
      84:     if (pfp == Nullfp)
      85:         fatal2("patch: can't create %s.\n", TMPPATNAME);
      86:     while (fgets(buf, sizeof buf, stdin) != Nullch)
      87:         fputs(buf, pfp);
      88:     Fclose(pfp);
      89:     filename = TMPPATNAME;
      90:     }
      91:     pfp = fopen(filename, "r");
      92:     if (pfp == Nullfp)
      93:     fatal2("patch file %s not found\n", filename);
      94:     Fstat(fileno(pfp), &filestat);
      95:     p_filesize = filestat.st_size;
      96:     next_intuit_at(0L,1L);          /* start at the beginning */
      97:     set_hunkmax();
      98: }
      99:
     100: /* Make sure our dynamically realloced tables are malloced to begin with. */
     101:
     102: void
     103: set_hunkmax()
     104: {
     105: #ifndef lint
     106:     if (p_line == Null(char**))
     107:     p_line = (char**) malloc((MEM)hunkmax * sizeof(char *));
     108:     if (p_len == Null(short*))
     109:     p_len  = (short*) malloc((MEM)hunkmax * sizeof(short));
     110: #endif
     111:     if (p_char == Nullch)
     112:     p_char = (char*)  malloc((MEM)hunkmax * sizeof(char));
     113: }
     114:
     115: /* Enlarge the arrays containing the current hunk of patch. */
     116:
     117: void
     118: grow_hunkmax()
     119: {
     120:     hunkmax *= 2;
     121:     /*
     122:      * Note that on most systems, only the p_line array ever gets fresh memory
     123:      * since p_len can move into p_line's old space, and p_char can move into
     124:      * p_len's old space.  Not on PDP-11's however.  But it doesn't matter.
     125:      */
     126:     assert(p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch);
     127: #ifndef lint
     128:     p_line = (char**) realloc((char*)p_line, (MEM)hunkmax * sizeof(char *));
     129:     p_len  = (short*) realloc((char*)p_len,  (MEM)hunkmax * sizeof(short));
     130:     p_char = (char*)  realloc((char*)p_char, (MEM)hunkmax * sizeof(char));
     131: #endif
     132:     if (p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch)
     133:     return;
     134:     if (!using_plan_a)
     135:     fatal1("patch: out of memory (grow_hunkmax)\n");
     136:     out_of_mem = TRUE;      /* whatever is null will be allocated again */
     137:                 /* from within plan_a(), of all places */
     138: }
     139:
     140: /* True if the remainder of the patch file contains a diff of some sort. */
     141:
     142: bool
     143: there_is_another_patch()
     144: {
     145:     if (p_base != 0L && p_base >= p_filesize) {
     146:     if (verbose)
     147:         say1("done\n");
     148:     return FALSE;
     149:     }
     150:     if (verbose)
     151:     say1("Hmm...");
     152:     diff_type = intuit_diff_type();
     153:     if (!diff_type) {
     154:     if (p_base != 0L) {
     155:         if (verbose)
     156:         say1("  Ignoring the trailing garbage.\ndone\n");
     157:     }
     158:     else
     159:         say1("  I can't seem to find a patch in there anywhere.\n");
     160:     return FALSE;
     161:     }
     162:     if (verbose)
     163:     say3("  %sooks like %s to me...\n",
     164:         (p_base == 0L ? "L" : "The next patch l"),
     165:         diff_type == CONTEXT_DIFF ? "a context diff" :
     166:         diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
     167:         diff_type == NORMAL_DIFF ? "a normal diff" :
     168:         "an ed script" );
     169:     if (p_indent && verbose)
     170:     say3("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
     171:     skip_to(p_start,p_sline);
     172:     while (filearg[0] == Nullch) {
     173:     if (force) {
     174:         say1("No file to patch.  Skipping...\n");
     175:         filearg[0] = savestr(bestguess);
     176:         return TRUE;
     177:     }
     178:     ask1("File to patch: ");
     179:     if (*buf != '\n') {
     180:         if (bestguess)
     181:         free(bestguess);
     182:         bestguess = savestr(buf);
     183:         filearg[0] = fetchname(buf, 0, FALSE);
     184:     }
     185:     if (filearg[0] == Nullch) {
     186:         ask1("No file found--skip this patch? [n] ");
     187:         if (*buf != 'y') {
     188:         continue;
     189:         }
     190:         if (verbose)
     191:         say1("Skipping patch...\n");
     192:         filearg[0] = fetchname(bestguess, 0, TRUE);
     193:         skip_rest_of_patch = TRUE;
     194:         return TRUE;
     195:     }
     196:     }
     197:     return TRUE;
     198: }
     199:
     200: /* Determine what kind of diff is in the remaining part of the patch file. */
     201:
     202: int
     203: intuit_diff_type()
     204: {
     205:     Reg4 long this_line = 0;
     206:     Reg5 long previous_line;
     207:     Reg6 long first_command_line = -1;
     208:     long fcl_line;
     209:     Reg7 bool last_line_was_command = FALSE;
     210:     Reg8 bool this_is_a_command = FALSE;
     211:     Reg9 bool stars_last_line = FALSE;
     212:     Reg10 bool stars_this_line = FALSE;
     213:     Reg3 int indent;
     214:     Reg1 char *s;
     215:     Reg2 char *t;
     216:     char *indtmp = Nullch;
     217:     char *oldtmp = Nullch;
     218:     char *newtmp = Nullch;
     219:     char *indname = Nullch;
     220:     char *oldname = Nullch;
     221:     char *newname = Nullch;
     222:     Reg11 int retval;
     223:     bool no_filearg = (filearg[0] == Nullch);
     224:
     225:     ok_to_create_file = FALSE;
     226:     Fseek(pfp, p_base, 0);
     227:     p_input_line = p_bline - 1;
     228:     for (;;) {
     229:     previous_line = this_line;
     230:     last_line_was_command = this_is_a_command;
     231:     stars_last_line = stars_this_line;
     232:     this_line = ftell(pfp);
     233:     indent = 0;
     234:     p_input_line++;
     235:     if (fgets(buf, sizeof buf, pfp) == Nullch) {
     236:         if (first_command_line >= 0L) {
     237:                     /* nothing but deletes!? */
     238:         p_start = first_command_line;
     239:         p_sline = fcl_line;
     240:         retval = ED_DIFF;
     241:         goto scan_exit;
     242:         }
     243:         else {
     244:         p_start = this_line;
     245:         p_sline = p_input_line;
     246:         retval = 0;
     247:         goto scan_exit;
     248:         }
     249:     }
     250:     for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
     251:         if (*s == '\t')
     252:         indent += 8 - (indent % 8);
     253:         else
     254:         indent++;
     255:     }
     256:     for (t=s; isdigit(*t) || *t == ','; t++) ;
     257:     this_is_a_command = (isdigit(*s) &&
     258:       (*t == 'd' || *t == 'c' || *t == 'a') );
     259:     if (first_command_line < 0L && this_is_a_command) {
     260:         first_command_line = this_line;
     261:         fcl_line = p_input_line;
     262:         p_indent = indent;      /* assume this for now */
     263:     }
     264:     if (!stars_last_line && strnEQ(s, "*** ", 4))
     265:         oldtmp = savestr(s+4);
     266:     else if (strnEQ(s, "--- ", 4))
     267:         newtmp = savestr(s+4);
     268:     else if (strnEQ(s, "Index:", 6))
     269:         indtmp = savestr(s+6);
     270:     else if (strnEQ(s, "Prereq:", 7)) {
     271:         for (t=s+7; isspace(*t); t++) ;
     272:         revision = savestr(t);
     273:         for (t=revision; *t && !isspace(*t); t++) ;
     274:         *t = '\0';
     275:         if (!*revision) {
     276:         free(revision);
     277:         revision = Nullch;
     278:         }
     279:     }
     280:     if ((!diff_type || diff_type == ED_DIFF) &&
     281:       first_command_line >= 0L &&
     282:       strEQ(s, ".\n") ) {
     283:         p_indent = indent;
     284:         p_start = first_command_line;
     285:         p_sline = fcl_line;
     286:         retval = ED_DIFF;
     287:         goto scan_exit;
     288:     }
     289:     stars_this_line = strnEQ(s, "********", 8);
     290:     if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
     291:          strnEQ(s, "*** ", 4)) {
     292:         if (!atol(s+4))
     293:         ok_to_create_file = TRUE;
     294:         /* if this is a new context diff the character just before */
     295:         /* the newline is a '*'. */
     296:         while (*s != '\n')
     297:         s++;
     298:         p_indent = indent;
     299:         p_start = previous_line;
     300:         p_sline = p_input_line - 1;
     301:         retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
     302:         goto scan_exit;
     303:     }
     304:     if ((!diff_type || diff_type == NORMAL_DIFF) &&
     305:       last_line_was_command &&
     306:       (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
     307:         p_start = previous_line;
     308:         p_sline = p_input_line - 1;
     309:         p_indent = indent;
     310:         retval = NORMAL_DIFF;
     311:         goto scan_exit;
     312:     }
     313:     }
     314:   scan_exit:
     315:     if (no_filearg) {
     316:     if (indtmp != Nullch)
     317:         indname = fetchname(indtmp, strippath, ok_to_create_file);
     318:     if (oldtmp != Nullch)
     319:         oldname = fetchname(oldtmp, strippath, ok_to_create_file);
     320:     if (newtmp != Nullch)
     321:         newname = fetchname(newtmp, strippath, ok_to_create_file);
     322:     if (oldname && newname) {
     323:         if (strlen(oldname) < strlen(newname))
     324:         filearg[0] = savestr(oldname);
     325:         else
     326:         filearg[0] = savestr(newname);
     327:     }
     328:     else if (oldname)
     329:         filearg[0] = savestr(oldname);
     330:     else if (newname)
     331:         filearg[0] = savestr(newname);
     332:     else if (indname)
     333:         filearg[0] = savestr(indname);
     334:     }
     335:     if (bestguess) {
     336:     free(bestguess);
     337:     bestguess = Nullch;
     338:     }
     339:     if (filearg[0] != Nullch)
     340:     bestguess = savestr(filearg[0]);
     341:     else if (indtmp != Nullch)
     342:     bestguess = fetchname(indtmp, strippath, TRUE);
     343:     else {
     344:     if (oldtmp != Nullch)
     345:         oldname = fetchname(oldtmp, strippath, TRUE);
     346:     if (newtmp != Nullch)
     347:         newname = fetchname(newtmp, strippath, TRUE);
     348:     if (oldname && newname) {
     349:         if (strlen(oldname) < strlen(newname))
     350:         bestguess = savestr(oldname);
     351:         else
     352:         bestguess = savestr(newname);
     353:     }
     354:     else if (oldname)
     355:         bestguess = savestr(oldname);
     356:     else if (newname)
     357:         bestguess = savestr(newname);
     358:     }
     359:     if (indtmp != Nullch)
     360:     free(indtmp);
     361:     if (oldtmp != Nullch)
     362:     free(oldtmp);
     363:     if (newtmp != Nullch)
     364:     free(newtmp);
     365:     if (indname != Nullch)
     366:     free(indname);
     367:     if (oldname != Nullch)
     368:     free(oldname);
     369:     if (newname != Nullch)
     370:     free(newname);
     371:     return retval;
     372: }
     373:
     374: /* Remember where this patch ends so we know where to start up again. */
     375:
     376: void
     377: next_intuit_at(file_pos,file_line)
     378: long file_pos;
     379: long file_line;
     380: {
     381:     p_base = file_pos;
     382:     p_bline = file_line;
     383: }
     384:
     385: /* Basically a verbose fseek() to the actual diff listing. */
     386:
     387: void
     388: skip_to(file_pos,file_line)
     389: long file_pos;
     390: long file_line;
     391: {
     392:     char *ret;
     393:
     394:     assert(p_base <= file_pos);
     395:     if (verbose && p_base < file_pos) {
     396:     Fseek(pfp, p_base, 0);
     397:     say1("The text leading up to this was:\n--------------------------\n");
     398:     while (ftell(pfp) < file_pos) {
     399:         ret = fgets(buf, sizeof buf, pfp);
     400:         assert(ret != Nullch);
     401:         say2("|%s", buf);
     402:     }
     403:     say1("--------------------------\n");
     404:     }
     405:     else
     406:     Fseek(pfp, file_pos, 0);
     407:     p_input_line = file_line - 1;
     408: }
     409:
     410: /* True if there is more of the current diff listing to process. */
     411:
     412: bool
     413: another_hunk()
     414: {
     415:     Reg1 char *s;
     416:     Reg8 char *ret;
     417:     Reg2 int context = 0;
     418:
     419:     while (p_end >= 0) {
     420:     if (p_end == p_efake)
     421:         p_end = p_bfake;        /* don't free twice */
     422:     else
     423:         free(p_line[p_end]);
     424:     p_end--;
     425:     }
     426:     assert(p_end == -1);
     427:     p_efake = -1;
     428:
     429:     p_max = hunkmax;            /* gets reduced when --- found */
     430:     if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
     431:     long line_beginning = ftell(pfp);
     432:                     /* file pos of the current line */
     433:     LINENUM repl_beginning = 0; /* index of --- line */
     434:     Reg4 LINENUM fillcnt = 0;   /* #lines of missing ptrn or repl */
     435:     Reg5 LINENUM fillsrc;       /* index of first line to copy */
     436:     Reg6 LINENUM filldst;       /* index of first missing line */
     437:     bool ptrn_spaces_eaten = FALSE; /* ptrn was slightly misformed */
     438:     Reg9 bool repl_could_be_missing = TRUE;
     439:                     /* no + or ! lines in this hunk */
     440:     bool repl_missing = FALSE;  /* we are now backtracking */
     441:     long repl_backtrack_position = 0;
     442:                     /* file pos of first repl line */
     443:     LINENUM repl_patch_line;    /* input line number for same */
     444:     Reg7 LINENUM ptrn_copiable = 0;
     445:                     /* # of copiable lines in ptrn */
     446:
     447:     ret = pgets(buf, sizeof buf, pfp);
     448:     p_input_line++;
     449:     if (ret == Nullch || strnNE(buf, "********", 8)) {
     450:         next_intuit_at(line_beginning,p_input_line);
     451:         return FALSE;
     452:     }
     453:     p_context = 100;
     454:     p_hunk_beg = p_input_line + 1;
     455:     while (p_end < p_max) {
     456:         line_beginning = ftell(pfp);
     457:         ret = pgets(buf, sizeof buf, pfp);
     458:         p_input_line++;
     459:         if (ret == Nullch) {
     460:         if (p_max - p_end < 4)
     461:             Strcpy(buf, "  \n");  /* assume blank lines got chopped */
     462:         else {
     463:             if (repl_beginning && repl_could_be_missing) {
     464:             repl_missing = TRUE;
     465:             goto hunk_done;
     466:             }
     467:             fatal1("Unexpected end of file in patch.\n");
     468:         }
     469:         }
     470:         p_end++;
     471:         assert(p_end < hunkmax);
     472:         p_char[p_end] = *buf;
     473: #ifdef zilog
     474:         p_line[(short)p_end] = Nullch;
     475: #else
     476:         p_line[p_end] = Nullch;
     477: #endif
     478:         switch (*buf) {
     479:         case '*':
     480:         if (strnEQ(buf, "********", 8)) {
     481:             if (repl_beginning && repl_could_be_missing) {
     482:             repl_missing = TRUE;
     483:             goto hunk_done;
     484:             }
     485:             else
     486:             fatal2("Unexpected end of hunk at line %ld.\n",
     487:                 p_input_line);
     488:         }
     489:         if (p_end != 0) {
     490:             if (repl_beginning && repl_could_be_missing) {
     491:             repl_missing = TRUE;
     492:             goto hunk_done;
     493:             }
     494:             fatal3("Unexpected *** at line %ld: %s", p_input_line, buf);
     495:         }
     496:         context = 0;
     497:         p_line[p_end] = savestr(buf);
     498:         if (out_of_mem) {
     499:             p_end--;
     500:             return FALSE;
     501:         }
     502:         for (s=buf; *s && !isdigit(*s); s++) ;
     503:         if (!*s)
     504:             goto malformed;
     505:         if (strnEQ(s,"0,0",3))
     506:             strcpy(s,s+2);
     507:         p_first = (LINENUM) atol(s);
     508:         while (isdigit(*s)) s++;
     509:         if (*s == ',') {
     510:             for (; *s && !isdigit(*s); s++) ;
     511:             if (!*s)
     512:             goto malformed;
     513:             p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
     514:         }
     515:         else if (p_first)
     516:             p_ptrn_lines = 1;
     517:         else {
     518:             p_ptrn_lines = 0;
     519:             p_first = 1;
     520:         }
     521:         p_max = p_ptrn_lines + 6;   /* we need this much at least */
     522:         while (p_max >= hunkmax)
     523:             grow_hunkmax();
     524:         p_max = hunkmax;
     525:         break;
     526:         case '-':
     527:         if (buf[1] == '-') {
     528:             if (repl_beginning ||
     529:             (p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n')))
     530:             {
     531:             if (p_end == 1) {
     532:                 /* `old' lines were omitted - set up to fill */
     533:                 /* them in from 'new' context lines. */
     534:                 p_end = p_ptrn_lines + 1;
     535:                 fillsrc = p_end + 1;
     536:                 filldst = 1;
     537:                 fillcnt = p_ptrn_lines;
     538:             }
     539:             else {
     540:                 if (repl_beginning) {
     541:                 if (repl_could_be_missing){
     542:                     repl_missing = TRUE;
     543:                     goto hunk_done;
     544:                 }
     545:                 fatal3(
     546: "Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
     547:                     p_input_line, p_hunk_beg + repl_beginning);
     548:                 }
     549:                 else {
     550:                 fatal4(
     551: "%s \"---\" at line %ld--check line numbers at line %ld.\n",
     552:                     (p_end <= p_ptrn_lines
     553:                     ? "Premature"
     554:                     : "Overdue" ),
     555:                     p_input_line, p_hunk_beg);
     556:                 }
     557:             }
     558:             }
     559:             repl_beginning = p_end;
     560:             repl_backtrack_position = ftell(pfp);
     561:             repl_patch_line = p_input_line;
     562:             p_line[p_end] = savestr(buf);
     563:             if (out_of_mem) {
     564:             p_end--;
     565:             return FALSE;
     566:             }
     567:             p_char[p_end] = '=';
     568:             for (s=buf; *s && !isdigit(*s); s++) ;
     569:             if (!*s)
     570:             goto malformed;
     571:             p_newfirst = (LINENUM) atol(s);
     572:             while (isdigit(*s)) s++;
     573:             if (*s == ',') {
     574:             for (; *s && !isdigit(*s); s++) ;
     575:             if (!*s)
     576:                 goto malformed;
     577:             p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
     578:             }
     579:             else if (p_newfirst)
     580:             p_repl_lines = 1;
     581:             else {
     582:             p_repl_lines = 0;
     583:             p_newfirst = 1;
     584:             }
     585:             p_max = p_repl_lines + p_end;
     586:             if (p_max > MAXHUNKSIZE)
     587:             fatal4("Hunk too large (%ld lines) at line %ld: %s",
     588:                   p_max, p_input_line, buf);
     589:             while (p_max >= hunkmax)
     590:             grow_hunkmax();
     591:             if (p_repl_lines != ptrn_copiable)
     592:             repl_could_be_missing = FALSE;
     593:             break;
     594:         }
     595:         goto change_line;
     596:         case '+':  case '!':
     597:         repl_could_be_missing = FALSE;
     598:           change_line:
     599:         if (buf[1] == '\n' && canonicalize)
     600:             strcpy(buf+1," \n");
     601:         if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' &&
     602:           repl_beginning && repl_could_be_missing) {
     603:             repl_missing = TRUE;
     604:             goto hunk_done;
     605:         }
     606:         if (context > 0) {
     607:             if (context < p_context)
     608:             p_context = context;
     609:             context = -1000;
     610:         }
     611:         p_line[p_end] = savestr(buf+2);
     612:         if (out_of_mem) {
     613:             p_end--;
     614:             return FALSE;
     615:         }
     616:         break;
     617:         case '\t': case '\n':   /* assume the 2 spaces got eaten */
     618:         if (repl_beginning && repl_could_be_missing &&
     619:           (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) {
     620:             repl_missing = TRUE;
     621:             goto hunk_done;
     622:         }
     623:         p_line[p_end] = savestr(buf);
     624:         if (out_of_mem) {
     625:             p_end--;
     626:             return FALSE;
     627:         }
     628:         if (p_end != p_ptrn_lines + 1) {
     629:             ptrn_spaces_eaten |= (repl_beginning != 0);
     630:             context++;
     631:             if (!repl_beginning)
     632:             ptrn_copiable++;
     633:             p_char[p_end] = ' ';
     634:         }
     635:         break;
     636:         case ' ':
     637:         if (!isspace(buf[1]) &&
     638:           repl_beginning && repl_could_be_missing) {
     639:             repl_missing = TRUE;
     640:             goto hunk_done;
     641:         }
     642:         context++;
     643:         if (!repl_beginning)
     644:             ptrn_copiable++;
     645:         p_line[p_end] = savestr(buf+2);
     646:         if (out_of_mem) {
     647:             p_end--;
     648:             return FALSE;
     649:         }
     650:         break;
     651:         default:
     652:         if (repl_beginning && repl_could_be_missing) {
     653:             repl_missing = TRUE;
     654:             goto hunk_done;
     655:         }
     656:         goto malformed;
     657:         }
     658:         /* set up p_len for strncmp() so we don't have to */
     659:         /* assume null termination */
     660:         if (p_line[p_end])
     661:         p_len[p_end] = strlen(p_line[p_end]);
     662:         else
     663:         p_len[p_end] = 0;
     664:     }
     665:
     666:     hunk_done:
     667:     if (p_end >=0 && !repl_beginning)
     668:         fatal2("No --- found in patch at line %ld\n", pch_hunk_beg());
     669:
     670:     if (repl_missing) {
     671:
     672:         /* reset state back to just after --- */
     673:         p_input_line = repl_patch_line;
     674:         for (p_end--; p_end > repl_beginning; p_end--)
     675:         free(p_line[p_end]);
     676:         Fseek(pfp, repl_backtrack_position, 0);
     677:
     678:         /* redundant 'new' context lines were omitted - set */
     679:         /* up to fill them in from the old file context */
     680:         fillsrc = 1;
     681:         filldst = repl_beginning+1;
     682:         fillcnt = p_repl_lines;
     683:         p_end = p_max;
     684:     }
     685:
     686:     if (diff_type == CONTEXT_DIFF &&
     687:       (fillcnt || (p_first > 1 && ptrn_copiable > 2*p_context)) ) {
     688:         if (verbose)
     689:         say4("%s\n%s\n%s\n",
     690: "(Fascinating--this is really a new-style context diff but without",
     691: "the telltale extra asterisks on the *** line that usually indicate",
     692: "the new style...)");
     693:         diff_type = NEW_CONTEXT_DIFF;
     694:     }
     695:
     696:     /* if there were omitted context lines, fill them in now */
     697:     if (fillcnt) {
     698:         p_bfake = filldst;      /* remember where not to free() */
     699:         p_efake = filldst + fillcnt - 1;
     700:         while (fillcnt-- > 0) {
     701:         while (fillsrc <= p_end && p_char[fillsrc] != ' ')
     702:             fillsrc++;
     703:         if (fillsrc > p_end)
     704:             fatal2("Replacement text or line numbers mangled in hunk at line %ld\n",
     705:             p_hunk_beg);
     706:         p_line[filldst] = p_line[fillsrc];
     707:         p_char[filldst] = p_char[fillsrc];
     708:         p_len[filldst] = p_len[fillsrc];
     709:         fillsrc++; filldst++;
     710:         }
     711:         while (fillsrc <= p_end && fillsrc != repl_beginning &&
     712:           p_char[fillsrc] != ' ')
     713:         fillsrc++;
     714: #ifdef DEBUGGING
     715:         if (debug & 64)
     716:         printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
     717:             fillsrc,filldst,repl_beginning,p_end+1);
     718: #endif
     719:         assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
     720:         assert(filldst==p_end+1 || filldst==repl_beginning);
     721:     }
     722:     }
     723:     else {              /* normal diff--fake it up */
     724:     char hunk_type;
     725:     Reg3 int i;
     726:     LINENUM min, max;
     727:     long line_beginning = ftell(pfp);
     728:
     729:     p_context = 0;
     730:     ret = pgets(buf, sizeof buf, pfp);
     731:     p_input_line++;
     732:     if (ret == Nullch || !isdigit(*buf)) {
     733:         next_intuit_at(line_beginning,p_input_line);
     734:         return FALSE;
     735:     }
     736:     p_first = (LINENUM)atol(buf);
     737:     for (s=buf; isdigit(*s); s++) ;
     738:     if (*s == ',') {
     739:         p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
     740:         while (isdigit(*s)) s++;
     741:     }
     742:     else
     743:         p_ptrn_lines = (*s != 'a');
     744:     hunk_type = *s;
     745:     if (hunk_type == 'a')
     746:         p_first++;          /* do append rather than insert */
     747:     min = (LINENUM)atol(++s);
     748:     for (; isdigit(*s); s++) ;
     749:     if (*s == ',')
     750:         max = (LINENUM)atol(++s);
     751:     else
     752:         max = min;
     753:     if (hunk_type == 'd')
     754:         min++;
     755:     p_end = p_ptrn_lines + 1 + max - min + 1;
     756:     if (p_end > MAXHUNKSIZE)
     757:         fatal4("Hunk too large (%ld lines) at line %ld: %s",
     758:           p_end, p_input_line, buf);
     759:     while (p_end >= hunkmax)
     760:         grow_hunkmax();
     761:     p_newfirst = min;
     762:     p_repl_lines = max - min + 1;
     763:     Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
     764:     p_line[0] = savestr(buf);
     765:     if (out_of_mem) {
     766:         p_end = -1;
     767:         return FALSE;
     768:     }
     769:     p_char[0] = '*';
     770:     for (i=1; i<=p_ptrn_lines; i++) {
     771:         ret = pgets(buf, sizeof buf, pfp);
     772:         p_input_line++;
     773:         if (ret == Nullch)
     774:         fatal2("Unexpected end of file in patch at line %ld.\n",
     775:           p_input_line);
     776:         if (*buf != '<')
     777:         fatal2("< expected at line %ld of patch.\n", p_input_line);
     778:         p_line[i] = savestr(buf+2);
     779:         if (out_of_mem) {
     780:         p_end = i-1;
     781:         return FALSE;
     782:         }
     783:         p_len[i] = strlen(p_line[i]);
     784:         p_char[i] = '-';
     785:     }
     786:     if (hunk_type == 'c') {
     787:         ret = pgets(buf, sizeof buf, pfp);
     788:         p_input_line++;
     789:         if (ret == Nullch)
     790:         fatal2("Unexpected end of file in patch at line %ld.\n",
     791:             p_input_line);
     792:         if (*buf != '-')
     793:         fatal2("--- expected at line %ld of patch.\n", p_input_line);
     794:     }
     795:     Sprintf(buf, "--- %ld,%ld\n", min, max);
     796:     p_line[i] = savestr(buf);
     797:     if (out_of_mem) {
     798:         p_end = i-1;
     799:         return FALSE;
     800:     }
     801:     p_char[i] = '=';
     802:     for (i++; i<=p_end; i++) {
     803:         ret = pgets(buf, sizeof buf, pfp);
     804:         p_input_line++;
     805:         if (ret == Nullch)
     806:         fatal2("Unexpected end of file in patch at line %ld.\n",
     807:             p_input_line);
     808:         if (*buf != '>')
     809:         fatal2("> expected at line %ld of patch.\n", p_input_line);
     810:         p_line[i] = savestr(buf+2);
     811:         if (out_of_mem) {
     812:         p_end = i-1;
     813:         return FALSE;
     814:         }
     815:         p_len[i] = strlen(p_line[i]);
     816:         p_char[i] = '+';
     817:     }
     818:     }
     819:     if (reverse)            /* backwards patch? */
     820:     if (!pch_swap())
     821:         say1("Not enough memory to swap next hunk!\n");
     822: #ifdef DEBUGGING
     823:     if (debug & 2) {
     824:     int i;
     825:     char special;
     826:
     827:     for (i=0; i <= p_end; i++) {
     828:         if (i == p_ptrn_lines)
     829:         special = '^';
     830:         else
     831:         special = ' ';
     832:         fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]);
     833:         Fflush(stderr);
     834:     }
     835:     }
     836: #endif
     837:     if (p_end+1 < hunkmax)  /* paranoia reigns supreme... */
     838:     p_char[p_end+1] = '^';  /* add a stopper for apply_hunk */
     839:     return TRUE;
     840:
     841: malformed:
     842:     fatal3("Malformed patch at line %ld: %s", p_input_line, buf);
     843:         /* about as informative as "Syntax error" in C */
     844:     return FALSE;   /* for lint */
     845: }
     846:
     847: /* Input a line from the patch file, worrying about indentation. */
     848:
     849: char *
     850: pgets(bf,sz,fp)
     851: char *bf;
     852: int sz;
     853: FILE *fp;
     854: {
     855:     char *ret = fgets(bf, sz, fp);
     856:     Reg1 char *s;
     857:     Reg2 int indent = 0;
     858:
     859:     if (p_indent && ret != Nullch) {
     860:     for (s=buf;
     861:       indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) {
     862:         if (*s == '\t')
     863:         indent += 8 - (indent % 7);
     864:         else
     865:         indent++;
     866:     }
     867:     if (buf != s)
     868:         Strcpy(buf, s);
     869:     }
     870:     return ret;
     871: }
     872:
     873: /* Reverse the old and new portions of the current hunk. */
     874:
     875: bool
     876: pch_swap()
     877: {
     878:     char **tp_line;     /* the text of the hunk */
     879:     short *tp_len;      /* length of each line */
     880:     char *tp_char;      /* +, -, and ! */
     881:     Reg1 LINENUM i;
     882:     Reg2 LINENUM n;
     883:     bool blankline = FALSE;
     884:     Reg3 char *s;
     885:
     886:     i = p_first;
     887:     p_first = p_newfirst;
     888:     p_newfirst = i;
     889:
     890:     /* make a scratch copy */
     891:
     892:     tp_line = p_line;
     893:     tp_len = p_len;
     894:     tp_char = p_char;
     895:     p_line = Null(char**);  /* force set_hunkmax to allocate again */
     896:     p_len = Null(short*);
     897:     p_char = Nullch;
     898:     set_hunkmax();
     899:     if (p_line == Null(char**) || p_len == Null(short*) || p_char == Nullch) {
     900: #ifndef lint
     901:     if (p_line == Null(char**))
     902:         free((char*)p_line);
     903:     p_line = tp_line;
     904:     if (p_len == Null(short*))
     905:         free((char*)p_len);
     906:     p_len = tp_len;
     907: #endif
     908:     if (p_char == Nullch)
     909:         free((char*)p_char);
     910:     p_char = tp_char;
     911:     return FALSE;       /* not enough memory to swap hunk! */
     912:     }
     913:
     914:     /* now turn the new into the old */
     915:
     916:     i = p_ptrn_lines + 1;
     917:     if (tp_char[i] == '\n') {       /* account for possible blank line */
     918:     blankline = TRUE;
     919:     i++;
     920:     }
     921:     if (p_efake >= 0) {         /* fix non-freeable ptr range */
     922:     if (p_efake <= i)
     923:         n = p_end - i + 1;
     924:     else
     925:         n = -i;
     926:     p_efake += n;
     927:     p_bfake += n;
     928:     }
     929:     for (n=0; i <= p_end; i++,n++) {
     930:     p_line[n] = tp_line[i];
     931:     p_char[n] = tp_char[i];
     932:     if (p_char[n] == '+')
     933:         p_char[n] = '-';
     934:     p_len[n] = tp_len[i];
     935:     }
     936:     if (blankline) {
     937:     i = p_ptrn_lines + 1;
     938:     p_line[n] = tp_line[i];
     939:     p_char[n] = tp_char[i];
     940:     p_len[n] = tp_len[i];
     941:     n++;
     942:     }
     943:     assert(p_char[0] == '=');
     944:     p_char[0] = '*';
     945:     for (s=p_line[0]; *s; s++)
     946:     if (*s == '-')
     947:         *s = '*';
     948:
     949:     /* now turn the old into the new */
     950:
     951:     assert(tp_char[0] == '*');
     952:     tp_char[0] = '=';
     953:     for (s=tp_line[0]; *s; s++)
     954:     if (*s == '*')
     955:         *s = '-';
     956:     for (i=0; n <= p_end; i++,n++) {
     957:     p_line[n] = tp_line[i];
     958:     p_char[n] = tp_char[i];
     959:     if (p_char[n] == '-')
     960:         p_char[n] = '+';
     961:     p_len[n] = tp_len[i];
     962:     }
     963:     assert(i == p_ptrn_lines + 1);
     964:     i = p_ptrn_lines;
     965:     p_ptrn_lines = p_repl_lines;
     966:     p_repl_lines = i;
     967: #ifndef lint
     968:     if (tp_line == Null(char**))
     969:     free((char*)tp_line);
     970:     if (tp_len == Null(short*))
     971:     free((char*)tp_len);
     972: #endif
     973:     if (tp_char == Nullch)
     974:     free((char*)tp_char);
     975:     return TRUE;
     976: }
     977:
     978: /* Return the specified line position in the old file of the old context. */
     979:
     980: LINENUM
     981: pch_first()
     982: {
     983:     return p_first;
     984: }
     985:
     986: /* Return the number of lines of old context. */
     987:
     988: LINENUM
     989: pch_ptrn_lines()
     990: {
     991:     return p_ptrn_lines;
     992: }
     993:
     994: /* Return the probable line position in the new file of the first line. */
     995:
     996: LINENUM
     997: pch_newfirst()
     998: {
     999:     return p_newfirst;
    1000: }
    1001:
    1002: /* Return the number of lines in the replacement text including context. */
    1003:
    1004: LINENUM
    1005: pch_repl_lines()
    1006: {
    1007:     return p_repl_lines;
    1008: }
    1009:
    1010: /* Return the number of lines in the whole hunk. */
    1011:
    1012: LINENUM
    1013: pch_end()
    1014: {
    1015:     return p_end;
    1016: }
    1017:
    1018: /* Return the number of context lines before the first changed line. */
    1019:
    1020: LINENUM
    1021: pch_context()
    1022: {
    1023:     return p_context;
    1024: }
    1025:
    1026: /* Return the length of a particular patch line. */
    1027:
    1028: short
    1029: pch_line_len(line)
    1030: LINENUM line;
    1031: {
    1032:     return p_len[line];
    1033: }
    1034:
    1035: /* Return the control character (+, -, *, !, etc) for a patch line. */
    1036:
    1037: char
    1038: pch_char(line)
    1039: LINENUM line;
    1040: {
    1041:     return p_char[line];
    1042: }
    1043:
    1044: /* Return a pointer to a particular patch line. */
    1045:
    1046: char *
    1047: pfetch(line)
    1048: LINENUM line;
    1049: {
    1050:     return p_line[line];
    1051: }
    1052:
    1053: /* Return where in the patch file this hunk began, for error messages. */
    1054:
    1055: LINENUM
    1056: pch_hunk_beg()
    1057: {
    1058:     return p_hunk_beg;
    1059: }
    1060:
    1061: /* Apply an ed script by feeding ed itself. */
    1062:
    1063: void
    1064: do_ed_script()
    1065: {
    1066:     Reg1 char *t;
    1067:     Reg2 long beginning_of_this_line;
    1068:     Reg3 bool this_line_is_command = FALSE;
    1069:     Reg4 FILE *pipefp;
    1070:     FILE *popen();
    1071:
    1072:     if (!skip_rest_of_patch) {
    1073:     Unlink(TMPOUTNAME);
    1074:     copy_file(filearg[0], TMPOUTNAME);
    1075:     if (verbose)
    1076:         Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
    1077:     else
    1078:         Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
    1079:     pipefp = popen(buf, "w");
    1080:     }
    1081:     for (;;) {
    1082:     beginning_of_this_line = ftell(pfp);
    1083:     if (pgets(buf, sizeof buf, pfp) == Nullch) {
    1084:         next_intuit_at(beginning_of_this_line,p_input_line);
    1085:         break;
    1086:     }
    1087:     p_input_line++;
    1088:     for (t=buf; isdigit(*t) || *t == ','; t++) ;
    1089:     this_line_is_command = (isdigit(*buf) &&
    1090:       (*t == 'd' || *t == 'c' || *t == 'a') );
    1091:     if (this_line_is_command) {
    1092:         if (!skip_rest_of_patch)
    1093:         fputs(buf, pipefp);
    1094:         if (*t != 'd') {
    1095:         while (pgets(buf, sizeof buf, pfp) != Nullch) {
    1096:             p_input_line++;
    1097:             if (!skip_rest_of_patch)
    1098:             fputs(buf, pipefp);
    1099:             if (strEQ(buf, ".\n"))
    1100:             break;
    1101:         }
    1102:         }
    1103:     }
    1104:     else {
    1105:         next_intuit_at(beginning_of_this_line,p_input_line);
    1106:         break;
    1107:     }
    1108:     }
    1109:     if (skip_rest_of_patch)
    1110:     return;
    1111:     fprintf(pipefp, "w\n");
    1112:     fprintf(pipefp, "q\n");
    1113:     Fflush(pipefp);
    1114:     Pclose(pipefp);
    1115:     ignore_signals();
    1116:     if (move_file(TMPOUTNAME, outname) < 0) {
    1117:     toutkeep = TRUE;
    1118:     chmod(TMPOUTNAME, filemode);
    1119:     }
    1120:     else
    1121:     chmod(outname, filemode);
    1122:     set_signals(1);
    1123: }

#### Defined functions

another_hunk defined in line 412; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 179
- in /usr/src/usr.bin/patch/pch.h line 22

do_ed_script defined in line 1063; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 161
- in /usr/src/usr.bin/patch/pch.h line 36

grow_hunkmax defined in line 117; used 4 times

- in line 523, 590, 760
- in /usr/src/usr.bin/patch/pch.h line 17

intuit_diff_type defined in line 202; used 2 times

- in line 152
- in /usr/src/usr.bin/patch/pch.h line 19

next_intuit_at defined in line 376; used 6 times

- in line 96, 450, 733, 1084, 1105
- in /usr/src/usr.bin/patch/pch.h line 20

open_patch_file defined in line 78; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 147
- in /usr/src/usr.bin/patch/pch.h line 15

pch_char defined in line 1037; used 17 times

- in /usr/src/usr.bin/patch/patch.c line 537, 558, 585-589(3), 607, 623(2), 629-633(3), 639, 650, 660, 666, 678
- in /usr/src/usr.bin/patch/pch.h line 33

pch_context defined in line 1020; used 3 times

- in /usr/src/usr.bin/patch/patch.c line 182, 487
- in /usr/src/usr.bin/patch/pch.h line 31

pch_end defined in line 1012; used 3 times

- in /usr/src/usr.bin/patch/patch.c line 526, 582
- in /usr/src/usr.bin/patch/pch.h line 30

pch_first defined in line 980; used 3 times

- in /usr/src/usr.bin/patch/patch.c line 481, 528
- in /usr/src/usr.bin/patch/pch.h line 26

pch_hunk_beg defined in line 1055; used 4 times

- in line 668
- in /usr/src/usr.bin/patch/patch.c line 625-626(2)
- in /usr/src/usr.bin/patch/pch.h line 32

pch_line_len defined in line 1028; used 3 times

- in /usr/src/usr.bin/patch/patch.c line 770-775(2)
- in /usr/src/usr.bin/patch/pch.h line 25

pch_newfirst defined in line 996; used 3 times

- in /usr/src/usr.bin/patch/patch.c line 236, 529
- in /usr/src/usr.bin/patch/pch.h line 28

pch_ptrn_lines defined in line 988; used 5 times

- in /usr/src/usr.bin/patch/patch.c line 483, 530, 574, 764
- in /usr/src/usr.bin/patch/pch.h line 27

pch_repl_lines defined in line 1004; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 531
- in /usr/src/usr.bin/patch/pch.h line 29

pch_swap defined in line 875; used 6 times

- in line 820
- in /usr/src/usr.bin/patch/patch.c line 190, 199-204(2), 222
- in /usr/src/usr.bin/patch/pch.h line 23

pfetch defined in line 1046; used 11 times

- in /usr/src/usr.bin/patch/patch.c line 555-558(2), 600, 619, 641, 651, 679, 769-774(2)
- in /usr/src/usr.bin/patch/pch.h line 24, 34

pgets defined in line 849; used 9 times

- in line 447, 457, 730, 771, 787, 803, 1083, 1095
- in /usr/src/usr.bin/patch/pch.h line 35

re_patch defined in line 64; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 328
- in /usr/src/usr.bin/patch/pch.h line 14

set_hunkmax defined in line 102; used 4 times

- in line 97, 898
- in /usr/src/usr.bin/patch/inp.c line 132
- in /usr/src/usr.bin/patch/pch.h line 16

skip_to defined in line 387; used 2 times

- in line 171
- in /usr/src/usr.bin/patch/pch.h line 21

there_is_another_patch defined in line 142; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 148
- in /usr/src/usr.bin/patch/pch.h line 18

#### Defined variables

hunkmax defined in line 52; used 14 times

- in line 107-112(3), 120, 128-130(3), 429, 471, 522-524(2), 589, 759, 837

p_base defined in line 54; used 9 times

- in line 145(2), 154, 164, 226, 381, 394-396(3)

p_bfake defined in line 60; used 3 times

- in line 421, 698, 927

p_bline defined in line 55; used 2 times

- in line 227, 382

p_char defined in line 51; used 36 times

- in line 111-112(2), 126-132(4), 472, 529, 567, 633, 701, 707-712(3), 769, 784, 801, 816, 832, 838, 894-899(3), 908-910(3), 931-933(3), 939-944(3), 958-960(3), 1041

p_context defined in line 47; used 6 times

- in line 453, 607-608(2), 687, 729, 1023

p_efake defined in line 59; used 6 times

- in line 420, 427, 699, 921-926(3)

p_end defined in line 45; used 68 times

- in line 71, 419-426(6), 455-460(2), 470-476(5), 489, 497-499(2), 529-535(5), 552, 559-567(4), 585, 611-613(2), 623-633(4), 645-647(2), 660-667(5), 674-675(4), 683, 701-703(2), 711, 717-720(3), 755-759(4), 766, 780, 798-802(2), 812, 827, 837-838(2), 923, 929, 956, 1015

p_filesize defined in line 40; used 2 times

- in line 95, 145

p_first defined in line 41; used 14 times

- in line 67, 507, 513-519(3), 687, 736-739(2), 746, 763(2), 886-887(2), 983

p_hunk_beg defined in line 58; used 5 times

- in line 454, 547, 555, 705, 1058

p_indent defined in line 53; used 10 times

- in line 73, 169-170(3), 262, 283, 298, 309, 859-861(2)

p_input_line defined in line 48; used 35 times

- in line 227, 234, 245, 261, 300, 308, 407, 448-458(4), 487, 494, 547, 555, 561, 588, 673, 731-733(2), 758, 772-777(3), 788-793(3), 804-809(3), 842, 1084-1087(2), 1096, 1105

p_len defined in line 50; used 22 times

- in line 108-109(2), 126-132(4), 661-663(2), 708(2), 783, 815, 893-906(6), 934, 940, 961, 1032

p_line defined in line 49; used 37 times

- in line 106-107(2), 126-132(4), 423, 474-476(2), 497, 562, 611, 623, 645, 660-661(2), 675, 706(2), 764, 778-783(2), 796, 810-815(2), 832, 892-903(6), 930, 938, 945, 957, 1050

p_max defined in line 46; used 12 times

- in line 72, 429, 455-460(2), 521-524(3), 585-589(4), 683

p_newfirst defined in line 42; used 9 times

- in line 68, 571, 577-583(3), 761, 887-888(2), 999

p_ptrn_lines defined in line 43; used 22 times

- in line 69, 513-521(4), 529-537(3), 552, 628, 739-743(2), 755, 763, 770, 828, 916, 937, 963-965(3), 991

p_repl_lines defined in line 44; used 11 times

- in line 70, 577-585(4), 591, 682, 762, 965-966(2), 1007

p_sline defined in line 57; used 6 times

- in line 171, 239, 245, 285, 300, 308

p_start defined in line 56; used 6 times

- in line 171, 238, 244, 284, 299, 307

Last modified: 1988-06-23 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3757 |