Lines 181-186
Link Here
|
181 |
}; |
181 |
}; |
182 |
|
182 |
|
183 |
#define diff_output printf |
183 |
#define diff_output printf |
|
|
184 |
#define MIN_PAD 1 |
184 |
static FILE *opentemp(const char *); |
185 |
static FILE *opentemp(const char *); |
185 |
static void output(char *, FILE *, char *, FILE *, int); |
186 |
static void output(char *, FILE *, char *, FILE *, int); |
186 |
static void check(FILE *, FILE *, int); |
187 |
static void check(FILE *, FILE *, int); |
Lines 196-201
Link Here
|
196 |
static void change(char *, FILE *, char *, FILE *, int, int, int, int, int *); |
197 |
static void change(char *, FILE *, char *, FILE *, int, int, int, int, int *); |
197 |
static void sort(struct line *, int); |
198 |
static void sort(struct line *, int); |
198 |
static void print_header(const char *, const char *); |
199 |
static void print_header(const char *, const char *); |
|
|
200 |
static void print_space(int, int, int); |
199 |
static bool ignoreline_pattern(char *); |
201 |
static bool ignoreline_pattern(char *); |
200 |
static bool ignoreline(char *, bool); |
202 |
static bool ignoreline(char *, bool); |
201 |
static int asciifile(FILE *); |
203 |
static int asciifile(FILE *); |
Lines 220-225
Link Here
|
220 |
static int pref, suff; /* length of prefix and suffix */ |
222 |
static int pref, suff; /* length of prefix and suffix */ |
221 |
static int slen[2]; |
223 |
static int slen[2]; |
222 |
static int anychange; |
224 |
static int anychange; |
|
|
225 |
static int hw, padding; /* half width and padding */ |
226 |
static int edoffset; |
223 |
static long *ixnew; /* will be overlaid on file[1] */ |
227 |
static long *ixnew; /* will be overlaid on file[1] */ |
224 |
static long *ixold; /* will be overlaid on klist */ |
228 |
static long *ixold; /* will be overlaid on klist */ |
225 |
static struct cand *clist; /* merely a free storage pot for candidates */ |
229 |
static struct cand *clist; /* merely a free storage pot for candidates */ |
Lines 263-268
Link Here
|
263 |
lastline = 0; |
267 |
lastline = 0; |
264 |
lastmatchline = 0; |
268 |
lastmatchline = 0; |
265 |
context_vec_ptr = context_vec_start - 1; |
269 |
context_vec_ptr = context_vec_start - 1; |
|
|
270 |
|
271 |
/* |
272 |
* hw excludes padding and make sure when -t is not used, |
273 |
* the second column always starts from the closest tab stop |
274 |
*/ |
275 |
if (diff_format == D_SIDEBYSIDE) { |
276 |
hw = width >> 1; |
277 |
padding = tabsize - (hw % tabsize); |
278 |
if ((flags & D_EXPANDTABS) != 0 || (padding % tabsize == 0)) |
279 |
padding = MIN_PAD; |
280 |
|
281 |
hw = (width >> 1) - |
282 |
((padding == MIN_PAD) ? (padding << 1) : padding) - 1; |
283 |
} |
284 |
|
285 |
|
266 |
if (flags & D_IGNORECASE) |
286 |
if (flags & D_IGNORECASE) |
267 |
chrtran = cup2low; |
287 |
chrtran = cup2low; |
268 |
else |
288 |
else |
Lines 865-871
Link Here
|
865 |
static void |
885 |
static void |
866 |
output(char *file1, FILE *f1, char *file2, FILE *f2, int flags) |
886 |
output(char *file1, FILE *f1, char *file2, FILE *f2, int flags) |
867 |
{ |
887 |
{ |
868 |
int m, i0, i1, j0, j1; |
888 |
int i, j, m, i0, i1, j0, j1, nc; |
869 |
|
889 |
|
870 |
rewind(f1); |
890 |
rewind(f1); |
871 |
rewind(f2); |
891 |
rewind(f2); |
Lines 874-881
Link Here
|
874 |
J[m + 1] = len[1] + 1; |
894 |
J[m + 1] = len[1] + 1; |
875 |
if (diff_format != D_EDIT) { |
895 |
if (diff_format != D_EDIT) { |
876 |
for (i0 = 1; i0 <= m; i0 = i1 + 1) { |
896 |
for (i0 = 1; i0 <= m; i0 = i1 + 1) { |
877 |
while (i0 <= m && J[i0] == J[i0 - 1] + 1) |
897 |
while (i0 <= m && J[i0] == J[i0 - 1] + 1){ |
|
|
898 |
if (diff_format == D_SIDEBYSIDE && |
899 |
suppress_common != 1) { |
900 |
nc = fetch(ixold, i0, i0, f1, '\0', |
901 |
1, flags); |
902 |
print_space(nc, |
903 |
(hw - nc) + (padding << 1) + 1, |
904 |
flags); |
905 |
fetch(ixnew, J[i0], J[i0], f2, '\0', |
906 |
0, flags); |
907 |
diff_output("\n"); |
908 |
} |
878 |
i0++; |
909 |
i0++; |
|
|
910 |
} |
879 |
j0 = J[i0 - 1] + 1; |
911 |
j0 = J[i0 - 1] + 1; |
880 |
i1 = i0 - 1; |
912 |
i1 = i0 - 1; |
881 |
while (i1 < m && J[i1 + 1] == 0) |
913 |
while (i1 < m && J[i1 + 1] == 0) |
Lines 882-888
Link Here
|
882 |
i1++; |
914 |
i1++; |
883 |
j1 = J[i1 + 1] - 1; |
915 |
j1 = J[i1 + 1] - 1; |
884 |
J[i1] = j1; |
916 |
J[i1] = j1; |
885 |
change(file1, f1, file2, f2, i0, i1, j0, j1, &flags); |
917 |
|
|
|
918 |
/* |
919 |
* When using side-by-side, lines from both of the |
920 |
* files are printed. The algorithm used by diff(1) |
921 |
* identifies the ranges in which two files differ. |
922 |
* See the change() function below. |
923 |
* The for loop below consumes the shorter range, |
924 |
* whereas one of the while loops deals with the |
925 |
* longer one. |
926 |
*/ |
927 |
if (diff_format == D_SIDEBYSIDE) { |
928 |
for (i=i0, j=j0; i<=i1 && j<=j1; i++, j++) |
929 |
change(file1, f1, file2, f2, i, i, |
930 |
j, j, &flags); |
931 |
|
932 |
while (i <= i1) { |
933 |
change(file1, f1, file2, f2, |
934 |
i, i, j+1, j, &flags); |
935 |
i++; |
936 |
} |
937 |
|
938 |
while (j <= j1) { |
939 |
change(file1, f1, file2, f2, |
940 |
i+1, i, j, j, &flags); |
941 |
j++; |
942 |
} |
943 |
} else |
944 |
change(file1, f1, file2, f2, i0, i1, j0, |
945 |
j1, &flags); |
886 |
} |
946 |
} |
887 |
} else { |
947 |
} else { |
888 |
for (i0 = m; i0 >= 1; i0 = i1 - 1) { |
948 |
for (i0 = m; i0 >= 1; i0 = i1 - 1) { |
Lines 987-993
Link Here
|
987 |
{ |
1047 |
{ |
988 |
static size_t max_context = 64; |
1048 |
static size_t max_context = 64; |
989 |
long curpos; |
1049 |
long curpos; |
990 |
int i, nc, f; |
1050 |
int i, nc; |
991 |
const char *walk; |
1051 |
const char *walk; |
992 |
bool skip_blanks; |
1052 |
bool skip_blanks; |
993 |
|
1053 |
|
Lines 1116-1132
Link Here
|
1116 |
diff_output("%c", *walk); |
1176 |
diff_output("%c", *walk); |
1117 |
} |
1177 |
} |
1118 |
} |
1178 |
} |
|
|
1179 |
if (diff_format == D_SIDEBYSIDE) { |
1180 |
if (a > b) { |
1181 |
print_space(0, hw + padding , *pflags); |
1182 |
} else { |
1183 |
nc = fetch(ixold, a, b, f1, '\0', 1, *pflags); |
1184 |
print_space(nc, hw - nc + padding, *pflags); |
1185 |
} |
1186 |
diff_output("%c", (a>b)? '>' : ((c>d)? '<' : '|')); |
1187 |
print_space(hw + padding + 1 , padding, *pflags); |
1188 |
fetch(ixnew, c, d, f2, '\0', 0, *pflags); |
1189 |
diff_output("\n"); |
1190 |
} |
1119 |
if (diff_format == D_NORMAL || diff_format == D_IFDEF) { |
1191 |
if (diff_format == D_NORMAL || diff_format == D_IFDEF) { |
1120 |
fetch(ixold, a, b, f1, '<', 1, *pflags); |
1192 |
fetch(ixold, a, b, f1, '<', 1, *pflags); |
1121 |
if (a <= b && c <= d && diff_format == D_NORMAL) |
1193 |
if (a <= b && c <= d && diff_format == D_NORMAL) |
1122 |
diff_output("---\n"); |
1194 |
diff_output("---\n"); |
1123 |
} |
1195 |
} |
1124 |
f = 0; |
1196 |
if (diff_format != D_GFORMAT && diff_format != D_SIDEBYSIDE) |
1125 |
if (diff_format != D_GFORMAT) |
1197 |
fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags); |
1126 |
f = fetch(ixnew, c, d, f2, diff_format == D_NORMAL ? '>' : '\0', 0, *pflags); |
1198 |
if (edoffset != 0 && diff_format == D_EDIT) { |
1127 |
if (f != 0 && diff_format == D_EDIT) { |
|
|
1128 |
/* |
1199 |
/* |
1129 |
* A non-zero return value for D_EDIT indicates that the |
1200 |
* A non-zero edoffset value for D_EDIT indicates that the |
1130 |
* last line printed was a bare dot (".") that has been |
1201 |
* last line printed was a bare dot (".") that has been |
1131 |
* escaped as ".." to prevent ed(1) from misinterpreting |
1202 |
* escaped as ".." to prevent ed(1) from misinterpreting |
1132 |
* it. We have to add a substitute command to change this |
1203 |
* it. We have to add a substitute command to change this |
Lines 1133-1142
Link Here
|
1133 |
* back and restart where we left off. |
1204 |
* back and restart where we left off. |
1134 |
*/ |
1205 |
*/ |
1135 |
diff_output(".\n"); |
1206 |
diff_output(".\n"); |
1136 |
diff_output("%ds/.//\n", a + f - 1); |
1207 |
diff_output("%ds/.//\n", a + edoffset - 1); |
1137 |
b = a + f - 1; |
1208 |
b = a + edoffset - 1; |
1138 |
a = b + 1; |
1209 |
a = b + 1; |
1139 |
c += f; |
1210 |
c += edoffset; |
1140 |
goto restart; |
1211 |
goto restart; |
1141 |
} |
1212 |
} |
1142 |
if ((diff_format == D_EDIT || diff_format == D_REVERSE) && c <= d) |
1213 |
if ((diff_format == D_EDIT || diff_format == D_REVERSE) && c <= d) |
Lines 1150-1158
Link Here
|
1150 |
static int |
1221 |
static int |
1151 |
fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags) |
1222 |
fetch(long *f, int a, int b, FILE *lb, int ch, int oldfile, int flags) |
1152 |
{ |
1223 |
{ |
1153 |
int i, j, c, lastc, col, nc; |
1224 |
int i, j, c, lastc, col, nc, newcol; |
1154 |
int newcol; |
|
|
1155 |
|
1225 |
|
|
|
1226 |
edoffset = 0; |
1227 |
nc = 0; |
1156 |
/* |
1228 |
/* |
1157 |
* When doing #ifdef's, copy down to current line |
1229 |
* When doing #ifdef's, copy down to current line |
1158 |
* if this is the first file, so that stuff makes it to output. |
1230 |
* if this is the first file, so that stuff makes it to output. |
Lines 1180-1191
Link Here
|
1180 |
} |
1252 |
} |
1181 |
for (i = a; i <= b; i++) { |
1253 |
for (i = a; i <= b; i++) { |
1182 |
fseek(lb, f[i - 1], SEEK_SET); |
1254 |
fseek(lb, f[i - 1], SEEK_SET); |
1183 |
nc = f[i] - f[i - 1]; |
1255 |
nc = (f[i] - f[i - 1]); |
1184 |
if ((diff_format != D_IFDEF && diff_format != D_GFORMAT) && |
1256 |
if (diff_format == D_SIDEBYSIDE && hw < nc) |
|
|
1257 |
nc = hw; |
1258 |
if ((diff_format != D_IFDEF && diff_format != D_GFORMAT) && |
1185 |
ch != '\0') { |
1259 |
ch != '\0') { |
1186 |
diff_output("%c", ch); |
1260 |
diff_output("%c", ch); |
1187 |
if (Tflag && (diff_format == D_NORMAL || diff_format == D_CONTEXT |
1261 |
if (Tflag && (diff_format == D_NORMAL || |
1188 |
|| diff_format == D_UNIFIED)) |
1262 |
diff_format == D_CONTEXT || |
|
|
1263 |
diff_format == D_UNIFIED)) |
1189 |
diff_output("\t"); |
1264 |
diff_output("\t"); |
1190 |
else if (diff_format != D_UNIFIED) |
1265 |
else if (diff_format != D_UNIFIED) |
1191 |
diff_output(" "); |
1266 |
diff_output(" "); |
Lines 1193-1211
Link Here
|
1193 |
col = 0; |
1268 |
col = 0; |
1194 |
for (j = 0, lastc = '\0'; j < nc; j++, lastc = c) { |
1269 |
for (j = 0, lastc = '\0'; j < nc; j++, lastc = c) { |
1195 |
if ((c = getc(lb)) == EOF) { |
1270 |
if ((c = getc(lb)) == EOF) { |
1196 |
if (diff_format == D_EDIT || diff_format == D_REVERSE || |
1271 |
if (diff_format == D_EDIT || |
|
|
1272 |
diff_format == D_REVERSE || |
1197 |
diff_format == D_NREVERSE) |
1273 |
diff_format == D_NREVERSE) |
1198 |
warnx("No newline at end of file"); |
1274 |
warnx("No newline at end of file"); |
1199 |
else |
1275 |
else |
1200 |
diff_output("\n\\ No newline at end of " |
1276 |
diff_output("\n\\ No newline at end of " |
1201 |
"file\n"); |
1277 |
"file\n"); |
1202 |
return (0); |
1278 |
return col; |
1203 |
} |
1279 |
} |
1204 |
if (c == '\t' && (flags & D_EXPANDTABS)) { |
1280 |
/* |
1205 |
newcol = ((col/tabsize)+1)*tabsize; |
1281 |
* when using --side-by-side, col needs to be increased |
1206 |
do { |
1282 |
* in any case to keep the columns aligned |
1207 |
diff_output(" "); |
1283 |
*/ |
1208 |
} while (++col < newcol); |
1284 |
if (c == '\t') { |
|
|
1285 |
if (flags & D_EXPANDTABS) { |
1286 |
newcol = ((col/tabsize)+1)*tabsize; |
1287 |
do { |
1288 |
if (diff_format == D_SIDEBYSIDE) |
1289 |
j++; |
1290 |
diff_output(" "); |
1291 |
} while (++col < newcol && j < nc); |
1292 |
} else { |
1293 |
if (diff_format == D_SIDEBYSIDE) { |
1294 |
if ((j + tabsize) > nc) { |
1295 |
diff_output("%*s", |
1296 |
nc - j,""); |
1297 |
j = col = nc; |
1298 |
} else { |
1299 |
diff_output("\t"); |
1300 |
col += tabsize - 1; |
1301 |
j += tabsize - 1; |
1302 |
} |
1303 |
} else { |
1304 |
diff_output("\t"); |
1305 |
col++; |
1306 |
} |
1307 |
} |
1209 |
} else { |
1308 |
} else { |
1210 |
if (diff_format == D_EDIT && j == 1 && c == '\n' |
1309 |
if (diff_format == D_EDIT && j == 1 && c == '\n' |
1211 |
&& lastc == '.') { |
1310 |
&& lastc == '.') { |
Lines 1212-1230
Link Here
|
1212 |
/* |
1311 |
/* |
1213 |
* Don't print a bare "." line |
1312 |
* Don't print a bare "." line |
1214 |
* since that will confuse ed(1). |
1313 |
* since that will confuse ed(1). |
1215 |
* Print ".." instead and return, |
1314 |
* Print ".." instead and set the, |
1216 |
* giving the caller an offset |
1315 |
* global variable edoffset to an |
1217 |
* from which to restart. |
1316 |
* offset from which to restart. |
|
|
1317 |
* The caller must check the value |
1318 |
* of edoffset |
1218 |
*/ |
1319 |
*/ |
1219 |
diff_output(".\n"); |
1320 |
diff_output(".\n"); |
1220 |
return (i - a + 1); |
1321 |
edoffset = i - a + 1; |
|
|
1322 |
return edoffset; |
1221 |
} |
1323 |
} |
1222 |
diff_output("%c", c); |
1324 |
/* when side-by-side, do not print a newline */ |
1223 |
col++; |
1325 |
if (diff_format != D_SIDEBYSIDE || c != '\n') { |
|
|
1326 |
diff_output("%c", c); |
1327 |
col++; |
1328 |
} |
1224 |
} |
1329 |
} |
1225 |
} |
1330 |
} |
1226 |
} |
1331 |
} |
1227 |
return (0); |
1332 |
return col; |
1228 |
} |
1333 |
} |
1229 |
|
1334 |
|
1230 |
/* |
1335 |
/* |
Lines 1578-1580
Link Here
|
1578 |
diff_output("%s %s\t%s\n", diff_format == D_CONTEXT ? "---" : "+++", |
1683 |
diff_output("%s %s\t%s\n", diff_format == D_CONTEXT ? "---" : "+++", |
1579 |
file2, buf2); |
1684 |
file2, buf2); |
1580 |
} |
1685 |
} |
|
|
1686 |
|
1687 |
/* |
1688 |
* Prints n number of space characters either by using tab |
1689 |
* or single space characters. |
1690 |
* nc is the preceding number of characters |
1691 |
*/ |
1692 |
static void |
1693 |
print_space(int nc, int n, int flags) { |
1694 |
int i, col; |
1695 |
|
1696 |
col = n; |
1697 |
if ((flags & D_EXPANDTABS) == 0) { |
1698 |
/* first tabstop may be closer than tabsize */ |
1699 |
i = tabsize - (nc % tabsize); |
1700 |
while (col >= tabsize) { |
1701 |
diff_output("\t"); |
1702 |
col -= i; |
1703 |
i = tabsize; |
1704 |
} |
1705 |
} |
1706 |
diff_output("%*s", col, ""); |
1707 |
} |