// Reverse a unidiff. // Bruno Haible 26.1.1999 /* * Copyright (C) 1995, 1996, 1997, 1999, 2000 Bruno Haible * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.io.*; class IntRef { int _i; public IntRef (int i) { _i = i; } public int getValue () { return _i; } public void setValue (int i) { _i = i; } } class DiffParse { public static Long parseInteger (String str, IntRef index) { int i = index.getValue(); boolean negative = false; if (str.charAt(i) == '-') { i++; negative = true; } int after_sign = i; long val = 0; for (;;) { char c = str.charAt(i); if (!(c >= '0' && c <= '9')) break; val = val*10 + (c-'0'); i++; } if (after_sign < i) { index.setValue(i); return new Long(negative ? -val : val); } else return null; // was: throw new NumberFormatException(); } } class ContextIn { DataInput _in_stream; int _linenum; // Number of last read line. String _line; // Last read line, or null. public ContextIn (DataInput stream) { _in_stream = stream; _linenum = 0; _line = null; } // Read the next line. public void nextLine () throws IOException { String line = _in_stream.readLine(); _linenum++; _line = line; } // Read the next line, if the last line has already been digested. public void prepareLine () throws IOException { if (_line == null) nextLine(); } } class ContextOut { DataOutput _out_stream; public ContextOut (DataOutput stream) { _out_stream = stream; } } class UnidiffHunkParams { // An unidiff hunk... int old_start_line; int old_line_count; int new_start_line; int new_line_count; } // ... is introduced by a line of the form "@@ -%d,%d +%d,%d @@%s". class UnidiffHunkParse { public static UnidiffHunkParams parseUnidiffHunkLine (String line) { IntRef index; int i; if (line.length() >= 11) { if ( line.charAt(0) == '@' && line.charAt(1) == '@' && line.charAt(2) == ' ' && line.charAt(3) == '-') { index = new IntRef(4); Long old_start_line = DiffParse.parseInteger(line,index); i = index.getValue(); if (old_start_line != null && i+1 <= line.length() && line.charAt(i) == ',') { index = new IntRef(i+1); Long old_line_count = DiffParse.parseInteger(line,index); i = index.getValue(); if (old_line_count != null && i+2 <= line.length() && line.charAt(i) == ' ' && line.charAt(i+1) == '+') { index = new IntRef(i+2); Long new_start_line = DiffParse.parseInteger(line,index); i = index.getValue(); if (new_start_line != null && i+1 <= line.length() && line.charAt(i) == ',') { index = new IntRef(i+1); Long new_line_count = DiffParse.parseInteger(line,index); i = index.getValue(); if (new_line_count != null && i+3 <= line.length() && line.charAt(i) == ' ' && line.charAt(i+1) == '@' && line.charAt(i+2) == '@') { UnidiffHunkParams result = new UnidiffHunkParams(); result.old_start_line = old_start_line.intValue(); result.old_line_count = old_line_count.intValue(); result.new_start_line = new_start_line.intValue(); result.new_line_count = new_line_count.intValue(); return result; } } } } } } return null; } } class udiffreverse { static class TwoPieceBuffer { StringVector _old_piece; StringVector _new_piece; StringVector _destination; TwoPieceBuffer (StringVector destination) { _old_piece = new StringVector(); _new_piece = new StringVector(); _destination = destination; } void add_old_line (String line) { _old_piece.addElement(line); } void add_new_line (String line) { _new_piece.addElement(line); } // flush the buffers static String prep_plus (String line) { return "+".concat(line); } static String prep_minus (String line) { return "-".concat(line); } void done () { StringEnumeration sloop; for (sloop = new StringVectorEnumerator(_new_piece); sloop.hasMoreElements(); ) _destination.addElement(prep_minus(sloop.nextElement())); for (sloop = new StringVectorEnumerator(_old_piece); sloop.hasMoreElements(); ) _destination.addElement(prep_plus(sloop.nextElement())); _old_piece.removeAllElements(); _new_piece.removeAllElements(); } } /* Should have multiple inheritance, really! static class ContextInOut { ContextIn _cin; ContextOut _cout; ContextInOut (DataInput istream, DataOutput ostream) { _cin = new ContextIn(istream); _cout = new ContextOut(ostream); } } */ static class ContextInOut extends ContextIn { DataOutput _out_stream; String _program_name; ContextInOut (DataInput istream, DataOutput ostream) { super (istream); _out_stream = ostream; _program_name = "udiffreverse"; } void doHunks () throws IOException { for (;;) { prepareLine(); if (_line == null) break; UnidiffHunkParams hunk_params = UnidiffHunkParse.parseUnidiffHunkLine(_line); if (hunk_params == null) break; int old_start_line = hunk_params.old_start_line; int new_start_line = hunk_params.new_start_line; int old_end_line = hunk_params.old_start_line + hunk_params.old_line_count - 1; int new_end_line = hunk_params.new_start_line + hunk_params.new_line_count - 1; int old_line_count = hunk_params.old_line_count; int new_line_count = hunk_params.new_line_count; StringVector lines = new StringVector(); TwoPieceBuffer buffer = new TwoPieceBuffer(lines); loop: for (;;) { _line = null; if (!((old_line_count > 0) || (new_line_count > 0))) break; prepareLine(); if (_line == null) break; if (!(_line.length() >= 1)) break; switch (_line.charAt(0)) { case ' ': { buffer.done(); lines.addElement(" ".concat(_line.substring(1))); old_line_count--; new_line_count--; break; } case '-': { buffer.add_old_line(_line.substring(1)); old_line_count--; break; } case '+': { buffer.add_new_line(_line.substring(1)); new_line_count--; break; } default: break loop; } } buffer.done(); _out_stream.writeBytes("@@ -"); _out_stream.writeBytes(String.valueOf(new_start_line)); _out_stream.writeBytes(","); _out_stream.writeBytes(String.valueOf(new_end_line-new_start_line+1)); _out_stream.writeBytes(" +"); _out_stream.writeBytes(String.valueOf(old_start_line)); _out_stream.writeBytes(","); _out_stream.writeBytes(String.valueOf(old_end_line-old_start_line+1)); _out_stream.writeBytes(" @@\n"); for (StringEnumeration sloop = new StringVectorEnumerator(lines); sloop.hasMoreElements(); ) { _out_stream.writeBytes(sloop.nextElement()); _out_stream.writeBytes("\n"); } if ((old_line_count > 0) || (new_line_count > 0)) { System.err.print(_program_name); System.err.print(": Warning: Incomplete hunk ending at line "); System.err.print(_linenum - (_line != null ? 1 : 0)); System.err.println(); } else if ((old_line_count != 0) || (new_line_count != 0)) { System.err.print(_program_name); System.err.print(": Warning: Overly long hunk ending at line "); System.err.print(_linenum - (_line != null ? 1 : 0)); System.err.println(); } } } void doFiles () throws IOException { for (;;) { String headline = null; String oldfile = null; String newfile = null; for (;;) { prepareLine(); if (_line == null) break; if (_line.length() >= 4 && _line.charAt(0) == 'd' && _line.charAt(1) == 'i' && _line.charAt(2) == 'f' && _line.charAt(3) == 'f') headline = _line; else if (_line.length() >= 4 && _line.charAt(0) == '-' && _line.charAt(1) == '-' && _line.charAt(2) == '-' && _line.charAt(3) == ' ') break; else { // System.err.print(_program_name); // System.err.print(": Warning: Junk at line "); // System.err.print(linenum); // System.err.print("."); // System.err.println(); _out_stream.writeBytes(_line); _out_stream.writeBytes("\n"); } _line = null; } if (_line == null) break; if (_line.length() >= 4 && _line.charAt(0) == '-' && _line.charAt(1) == '-' && _line.charAt(2) == '-' && _line.charAt(3) == ' ') { oldfile = _line.substring(4); nextLine(); } if (_line == null) break; if (_line.length() >= 4 && _line.charAt(0) == '+' && _line.charAt(1) == '+' && _line.charAt(2) == '+' && _line.charAt(3) == ' ') { newfile = _line.substring(4); nextLine(); } if (_line == null) break; if (headline != null) { _out_stream.writeBytes(headline); _out_stream.writeBytes("\n"); } if (oldfile != null && newfile != null) { _out_stream.writeBytes("--- "); _out_stream.writeBytes(newfile); _out_stream.writeBytes("\n"); _out_stream.writeBytes("+++ "); _out_stream.writeBytes(oldfile); _out_stream.writeBytes("\n"); } doHunks(); } } } // Main program! public static void main (String args[]) { ContextInOut context = new ContextInOut(new DataInputStream(System.in), new DataOutputStream(System.out)); try { context.doFiles(); } catch (IOException e) { System.exit(1); } if (System.out.checkError()) System.exit(1); } }