📄 pch.c
字号:
} if (rev) /* backwards patch? */ if (!pch_swap()) say ("Not enough memory to swap next hunk!\n"); if (debug & 2) { LINENUM i; char special; for (i=0; i <= p_end; i++) { if (i == p_ptrn_lines) special = '^'; else special = ' '; fprintf (stderr, "%s %c %c ", format_linenum (numbuf0, i), p_Char[i], special); pch_write_line (i, stderr); fflush (stderr); } } if (p_end+1 < hunkmax) /* paranoia reigns supreme... */ p_Char[p_end+1] = '^'; /* add a stopper for apply_hunk */ return 1;}static size_tget_line (void){ return pget_line (p_indent, p_rfc934_nesting, p_strip_trailing_cr, p_pass_comments_through);}/* Input a line from the patch file, worrying about indentation. Strip up to INDENT characters' worth of leading indentation. Then remove up to RFC934_NESTING instances of leading "- ". If STRIP_TRAILING_CR is true, remove any trailing carriage-return. Unless PASS_COMMENTS_THROUGH is true, ignore any resulting lines that begin with '#'; they're comments. Ignore any partial lines at end of input, but warn about them. Succeed if a line was read; it is terminated by "\n\0" for convenience. Return the number of characters read, including '\n' but not '\0'. Return -1 if we ran out of memory. */static size_tpget_line (int indent, int rfc934_nesting, bool strip_trailing_cr, bool pass_comments_through){ register FILE *fp = pfp; register int c; register int i; register char *b; register size_t s; do { i = 0; for (;;) { c = getc (fp); if (c == EOF) { if (ferror (fp)) read_fatal (); return 0; } if (indent <= i) break; if (c == ' ' || c == 'X') i++; else if (c == '\t') i = (i + 8) & ~7; else break; } i = 0; b = buf; while (c == '-' && 0 <= --rfc934_nesting) { c = getc (fp); if (c == EOF) goto patch_ends_in_middle_of_line; if (c != ' ') { i = 1; b[0] = '-'; break; } c = getc (fp); if (c == EOF) goto patch_ends_in_middle_of_line; } s = bufsize; for (;;) { if (i == s - 1) { s *= 2; b = realloc (b, s); if (!b) { if (!using_plan_a) memory_fatal (); return (size_t) -1; } buf = b; bufsize = s; } b[i++] = c; if (c == '\n') break; c = getc (fp); if (c == EOF) goto patch_ends_in_middle_of_line; } p_input_line++; } while (*b == '#' && !pass_comments_through); if (strip_trailing_cr && 2 <= i && b[i - 2] == '\r') b[i-- - 2] = '\n'; b[i] = '\0'; return i; patch_ends_in_middle_of_line: if (ferror (fp)) read_fatal (); say ("patch unexpectedly ends in middle of line\n"); return 0;}static boolincomplete_line (void){ register FILE *fp = pfp; register int c; register file_offset line_beginning = file_tell (fp); if (getc (fp) == '\\') { while ((c = getc (fp)) != '\n' && c != EOF) continue; return true; } else { /* We don't trust ungetc. */ Fseek (pfp, line_beginning, SEEK_SET); return false; }}/* Reverse the old and new portions of the current hunk. */boolpch_swap (void){ char **tp_line; /* the text of the hunk */ size_t *tp_len; /* length of each line */ char *tp_char; /* +, -, and ! */ register LINENUM i; register LINENUM n; bool blankline = false; register char *s; i = p_first; p_first = p_newfirst; p_newfirst = i; /* make a scratch copy */ tp_line = p_line; tp_len = p_len; tp_char = p_Char; p_line = 0; /* force set_hunkmax to allocate again */ p_len = 0; p_Char = 0; set_hunkmax(); if (!p_line || !p_len || !p_Char) { if (p_line) free (p_line); p_line = tp_line; if (p_len) free (p_len); p_len = tp_len; if (p_Char) free (p_Char); p_Char = tp_char; return false; /* not enough memory to swap hunk! */ } /* now turn the new into the old */ i = p_ptrn_lines + 1; if (tp_char[i] == '\n') { /* account for possible blank line */ blankline = true; i++; } if (p_efake >= 0) { /* fix non-freeable ptr range */ if (p_efake <= i) n = p_end - i + 1; else n = -i; p_efake += n; p_bfake += n; } for (n=0; i <= p_end; i++,n++) { p_line[n] = tp_line[i]; p_Char[n] = tp_char[i]; if (p_Char[n] == '+') p_Char[n] = '-'; p_len[n] = tp_len[i]; } if (blankline) { i = p_ptrn_lines + 1; p_line[n] = tp_line[i]; p_Char[n] = tp_char[i]; p_len[n] = tp_len[i]; n++; } assert(p_Char[0] == '='); p_Char[0] = '*'; for (s=p_line[0]; *s; s++) if (*s == '-') *s = '*'; /* now turn the old into the new */ assert(tp_char[0] == '*'); tp_char[0] = '='; for (s=tp_line[0]; *s; s++) if (*s == '*') *s = '-'; for (i=0; n <= p_end; i++,n++) { p_line[n] = tp_line[i]; p_Char[n] = tp_char[i]; if (p_Char[n] == '-') p_Char[n] = '+'; p_len[n] = tp_len[i]; } assert(i == p_ptrn_lines + 1); i = p_ptrn_lines; p_ptrn_lines = p_repl_lines; p_repl_lines = i; if (tp_line) free (tp_line); if (tp_len) free (tp_len); if (tp_char) free (tp_char); return true;}/* Return whether file WHICH (false = old, true = new) appears to nonexistent. Return 1 for empty, 2 for nonexistent. */intpch_says_nonexistent (bool which){ return p_says_nonexistent[which];}/* Return timestamp of patch header for file WHICH (false = old, true = new), or -1 if there was no timestamp or an error in the timestamp. */time_tpch_timestamp (bool which){ return p_timestamp[which];}/* Return the specified line position in the old file of the old context. */LINENUMpch_first (void){ return p_first;}/* Return the number of lines of old context. */LINENUMpch_ptrn_lines (void){ return p_ptrn_lines;}/* Return the probable line position in the new file of the first line. */LINENUMpch_newfirst (void){ return p_newfirst;}/* Return the number of lines in the replacement text including context. */LINENUMpch_repl_lines (void){ return p_repl_lines;}/* Return the number of lines in the whole hunk. */LINENUMpch_end (void){ return p_end;}/* Return the number of context lines before the first changed line. */LINENUMpch_prefix_context (void){ return p_prefix_context;}/* Return the number of context lines after the last changed line. */LINENUMpch_suffix_context (void){ return p_suffix_context;}/* Return the length of a particular patch line. */size_tpch_line_len (LINENUM line){ return p_len[line];}/* Return the control character (+, -, *, !, etc) for a patch line. */charpch_char (LINENUM line){ return p_Char[line];}/* Return a pointer to a particular patch line. */char *pfetch (LINENUM line){ return p_line[line];}/* Output a patch line. */boolpch_write_line (LINENUM line, FILE *file){ bool after_newline = p_line[line][p_len[line] - 1] == '\n'; if (! fwrite (p_line[line], sizeof (*p_line[line]), p_len[line], file)) write_fatal (); return after_newline;}/* Return where in the patch file this hunk began, for error messages. */LINENUMpch_hunk_beg (void){ return p_hunk_beg;}/* Is the newline-terminated line a valid `ed' command for patch input? If so, return the command character; if not, return 0. This accepts accepts just a subset of the valid commands, but it's good enough in practice. */static charget_ed_command_letter (char const *line){ char const *p = line; char letter; bool pair = false; if (! ISDIGIT (*p)) return 0; while (ISDIGIT (*++p)) continue; if (*p == ',') { if (! ISDIGIT (*++p)) return 0; while (ISDIGIT (*++p)) continue; pair = true; } letter = *p++; switch (letter) { case 'a': case 'i': if (pair) return 0; break; case 'c': case 'd': break; case 's': if (strncmp (p, "/.//", 4) != 0) return 0; p += 4; break; default: return 0; } while (*p == ' ' || *p == '\t') p++; if (*p == '\n') return letter; return 0;}/* Apply an ed script by feeding ed itself. */voiddo_ed_script (FILE *ofp){ static char const ed_program[] = ed_PROGRAM; register file_offset beginning_of_this_line; register FILE *pipefp = 0; register size_t chars_read; if (! dry_run && ! skip_rest_of_patch) { int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL; assert (! inerrno); TMPOUTNAME_needs_removal = 1; copy_file (inname, TMPOUTNAME, exclusive, instat.st_mode); sprintf (buf, "%s %s%s", ed_program, verbosity == VERBOSE ? "" : "- ", TMPOUTNAME); fflush (stdout); pipefp = popen(buf, binary_transput ? "wb" : "w"); if (!pipefp) pfatal ("Can't open pipe to %s", quotearg (buf)); } for (;;) { char ed_command_letter; beginning_of_this_line = file_tell (pfp); chars_read = get_line (); if (! chars_read) { next_intuit_at(beginning_of_this_line,p_input_line); break; } ed_command_letter = get_ed_command_letter (buf); if (ed_command_letter) { if (pipefp) if (! fwrite (buf, sizeof *buf, chars_read, pipefp)) write_fatal (); if (ed_command_letter != 'd' && ed_command_letter != 's') { p_pass_comments_through = true; while ((chars_read = get_line ()) != 0) { if (pipefp) if (! fwrite (buf, sizeof *buf, chars_read, pipefp)) write_fatal (); if (chars_read == 2 && strEQ (buf, ".\n")) break; } p_pass_comments_through = false; } } else { next_intuit_at(beginning_of_this_line,p_input_line); break; } } if (!pipefp) return; if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, pipefp) == 0 || fflush (pipefp) != 0) write_fatal (); if (pclose (pipefp) != 0) fatal ("%s FAILED", ed_program); if (ofp) { FILE *ifp = fopen (TMPOUTNAME, binary_transput ? "rb" : "r"); int c; if (!ifp) pfatal ("can't open `%s'", TMPOUTNAME); while ((c = getc (ifp)) != EOF) if (putc (c, ofp) == EOF) write_fatal (); if (ferror (ifp) || fclose (ifp) != 0) read_fatal (); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -