1*31207Smckusick /*
2*31207Smckusick * Copyright (c) 1987 Regents of the University of California.
3*31207Smckusick * All rights reserved. The Berkeley software License Agreement
4*31207Smckusick * specifies the terms and conditions for redistribution.
5*31207Smckusick */
6*31207Smckusick
7*31207Smckusick #ifndef lint
8*31207Smckusick static char sccsid[] = "@(#)chgbars.c 5.1 (Berkeley) 05/25/87";
9*31207Smckusick #endif not lint
10*31207Smckusick
11*31207Smckusick /*
12*31207Smckusick * Derived from original program by A. Dain Samples.
13*31207Smckusick *
14*31207Smckusick * The program chgbars will accept the output from a diff comparison of
15*31207Smckusick * two versions of a file. It will then read the new version of the file
16*31207Smckusick * and insert the appropriate troff commands to put change bars in the
17*31207Smckusick * right margin. Typing 'chgbars' without any arguments will give you
18*31207Smckusick * some documentation and an example.
19*31207Smckusick *
20*31207Smckusick * Caveat: If you make a change inside an equation or table, the
21*31207Smckusick * preprocessors eqn and tbl may not like what chgbars does to the file.
22*31207Smckusick * You may have to go into the output from chgbars to remove or rearrange
23*31207Smckusick * some of the lines of the form '.mc | \"open' or '.mc \"close' in
24*31207Smckusick * order to get through tbl or eqn.
25*31207Smckusick *
26*31207Smckusick * Unfortunately, users of RCS will be disappointed: one cannot use rcsdiff.
27*31207Smckusick * Rcsdiff compares the files in the wrong order.
28*31207Smckusick *
29*31207Smckusick * There is a relatively easy way to do the job with the tools sed and awk.
30*31207Smckusick * However, sed does not allow enough commands to process large documents.
31*31207Smckusick * In the true spirit of a filter/tool, chgbars is limited only by the
32*31207Smckusick * amount of memory on the machine, and is fast and useful.
33*31207Smckusick *
34*31207Smckusick * The modifications necessary are outlined:
35*31207Smckusick *
36*31207Smckusick * FORM OF DIFF OUTPUT COMMENT NEW SED COMMANDS
37*31207Smckusick * ================================================================
38*31207Smckusick * 100a means those lines 100a\\
39*31207Smckusick * L1 were deleted from .mc |\\
40*31207Smckusick * L2 oldfile .mc
41*31207Smckusick * :
42*31207Smckusick * Ln
43*31207Smckusick * .
44*31207Smckusick * ----------------------------------------------------------------
45*31207Smckusick * 100c
46*31207Smckusick * L1
47*31207Smckusick * L2
48*31207Smckusick * :
49*31207Smckusick * Ln
50*31207Smckusick * .
51*31207Smckusick * means that line 100 in newfile replaced all those lines in oldfile.
52*31207Smckusick * 100a
53*31207Smckusick * .mc
54*31207Smckusick * 99 a
55*31207Smckusick * .mc |
56*31207Smckusick * ----------------------------------------------------------------
57*31207Smckusick * 100d that line was added 100a\\
58*31207Smckusick * to oldfile .mc
59*31207Smckusick * 99a\\
60*31207Smckusick * .mc |
61*31207Smckusick * ----------------------------------------------------------------
62*31207Smckusick * 100,200d those lines were 200a\\
63*31207Smckusick * added to oldfile .mc
64*31207Smckusick * 99a\\
65*31207Smckusick * .mc |
66*31207Smckusick * ----------------------------------------------------------------
67*31207Smckusick * 100,200c
68*31207Smckusick * L1
69*31207Smckusick * L2
70*31207Smckusick * :
71*31207Smckusick * Ln
72*31207Smckusick * .
73*31207Smckusick * means lines 100 to 200 of newfile replaced all the following lines
74*31207Smckusick * in oldfile.
75*31207Smckusick * 200a
76*31207Smckusick * .mc
77*31207Smckusick * 99a
78*31207Smckusick * .mc |
79*31207Smckusick * ----------------------------------------------------------------
80*31207Smckusick */
81*31207Smckusick
82*31207Smckusick #include <stdio.h>
83*31207Smckusick #include <strings.h>
84*31207Smckusick #include <ctype.h>
85*31207Smckusick
86*31207Smckusick #define dbg(s) /* fprintf(stderr,"s\n") */
87*31207Smckusick #define none 0
88*31207Smckusick #define open 1
89*31207Smckusick #define close 2
90*31207Smckusick #define both 3
91*31207Smckusick
92*31207Smckusick char (*action)[];
93*31207Smckusick FILE *file1, *file2;
94*31207Smckusick char linebuf[1024];
95*31207Smckusick char nextch;
96*31207Smckusick int num1, num2, t, line;
97*31207Smckusick char lineact;
98*31207Smckusick
99*31207Smckusick #ifndef lint
100*31207Smckusick char copyright[] =
101*31207Smckusick "@(#) Copyright (c) 1986 Regents of the University of California.\n\
102*31207Smckusick All rights reserved.\n";
103*31207Smckusick #endif not lint
104*31207Smckusick
main(argc,argv)105*31207Smckusick main(argc, argv)
106*31207Smckusick int argc;
107*31207Smckusick char *argv[];
108*31207Smckusick {
109*31207Smckusick register char *p;
110*31207Smckusick register int i;
111*31207Smckusick
112*31207Smckusick if (argc < 2)
113*31207Smckusick usage();
114*31207Smckusick /* open $1 */
115*31207Smckusick if (strcmp(argv[1], "-") == 0) {
116*31207Smckusick file1 = stdin;
117*31207Smckusick if (argc <= 2)
118*31207Smckusick usage();
119*31207Smckusick } else if ((file1 = fopen(argv[1], "r")) == NULL) {
120*31207Smckusick fprintf(stderr, "error: can't open %s\n", argv[1]);
121*31207Smckusick exit(1);
122*31207Smckusick }
123*31207Smckusick /*
124*31207Smckusick * read each entry setting the appropriate entry in action[]
125*31207Smckusick *
126*31207Smckusick * get the first line number: since diff -e puts the numbers out
127*31207Smckusick * in reverse order, this tells us how big to make the file
128*31207Smckusick */
129*31207Smckusick readline();
130*31207Smckusick if (lineact == 'a')
131*31207Smckusick t = num1;
132*31207Smckusick else
133*31207Smckusick t = num2;
134*31207Smckusick action = (char (*)[]) malloc(t + 1);
135*31207Smckusick for (p = (char *) action, i = 0; i < t; i++)
136*31207Smckusick *p++ = (char) none;
137*31207Smckusick while (!feof(file1)) {
138*31207Smckusick if (lineact == 'a') {
139*31207Smckusick (*action)[num1] = both;
140*31207Smckusick skiptilldot();
141*31207Smckusick } else {
142*31207Smckusick (*action)[num1 - 1] = open;
143*31207Smckusick (*action)[num2] = close;
144*31207Smckusick if (lineact == 'c')
145*31207Smckusick skiptilldot();
146*31207Smckusick else
147*31207Smckusick skiptilleol();
148*31207Smckusick }
149*31207Smckusick readline();
150*31207Smckusick }
151*31207Smckusick fclose(file1);
152*31207Smckusick /* open $2 */
153*31207Smckusick if (argc == 2)
154*31207Smckusick file2 = stdin;
155*31207Smckusick else
156*31207Smckusick file2 = fopen(argv[2], "r");
157*31207Smckusick if (file2 == NULL) {
158*31207Smckusick fprintf(stderr, "can't open %2\n", argv[2]);
159*31207Smckusick exit(1);
160*31207Smckusick }
161*31207Smckusick line = 0;
162*31207Smckusick while (!feof(file2)) {
163*31207Smckusick if (line != 0)
164*31207Smckusick fputs(linebuf, stdout);
165*31207Smckusick if (line <= t) {
166*31207Smckusick switch ((*action)[line]) {
167*31207Smckusick case open:
168*31207Smckusick printf(".mc | \\\"open\n");
169*31207Smckusick break;
170*31207Smckusick case close:
171*31207Smckusick printf(".mc \\\"close\n");
172*31207Smckusick break;
173*31207Smckusick case both:
174*31207Smckusick printf(".mc | \\\"both\n");
175*31207Smckusick printf(".mc\n");
176*31207Smckusick break;
177*31207Smckusick default:;
178*31207Smckusick }
179*31207Smckusick }
180*31207Smckusick fgets(linebuf, sizeof(linebuf), file2);
181*31207Smckusick line++;
182*31207Smckusick }
183*31207Smckusick if (line <= t) {
184*31207Smckusick fprintf(stderr, "oops: number of lines read does not match\n");
185*31207Smckusick fprintf(stderr, "number of lines expected\n");
186*31207Smckusick exit(1);
187*31207Smckusick }
188*31207Smckusick exit(0);
189*31207Smckusick }
190*31207Smckusick
usage()191*31207Smckusick usage()
192*31207Smckusick {
193*31207Smckusick
194*31207Smckusick fprintf(stderr, "Usage:\n");
195*31207Smckusick fprintf(stderr, "\tchgbars diff.out\n");
196*31207Smckusick fprintf(stderr, "\t\t\treads the output from diff, and expects the\n");
197*31207Smckusick fprintf(stderr, "\t\t\tfile to be modified on stdin\n");
198*31207Smckusick fprintf(stderr, "\tchgbars diff.out file.tbm\n");
199*31207Smckusick fprintf(stderr, "\t\t\tboth the output from diff and the file to be\n");
200*31207Smckusick fprintf(stderr, "\t\t\tmodified are stated explicitly\n");
201*31207Smckusick fprintf(stderr, "\tchgbars - file.tbm\n");
202*31207Smckusick fprintf(stderr, "\t\t\treads the output from diff on stdin\n");
203*31207Smckusick fprintf(stderr, "\nE.g.\n");
204*31207Smckusick fprintf(stderr, "diff -b -e newfile oldfile | chgbars - newfile | vtroff -ms\n");
205*31207Smckusick fprintf(stderr, "\t(note the order of the files in the diff command!)\n");
206*31207Smckusick fprintf(stderr, "\n\nBe forewarned: chgbars does not know about tables or equations.\n");
207*31207Smckusick fprintf(stderr, "If any part of a table or equation is changed, chgbars will insert the\n");
208*31207Smckusick fprintf(stderr, ".mc commands, whether tbl or eqn likes it or not.\n");
209*31207Smckusick fprintf(stderr, "This means that you may have to do some hand editing of the output of\n");
210*31207Smckusick fprintf(stderr, "chgbars to make it acceptable to one or both of these preprocessors.\n");
211*31207Smckusick
212*31207Smckusick exit(1);
213*31207Smckusick }
214*31207Smckusick
readnum()215*31207Smckusick readnum()
216*31207Smckusick {
217*31207Smckusick int num;
218*31207Smckusick
219*31207Smckusick dbg(readnum);
220*31207Smckusick num = 0;
221*31207Smckusick nextch = getc(file1);
222*31207Smckusick while (isdigit(nextch)) {
223*31207Smckusick num = num * 10 + nextch - '0';
224*31207Smckusick nextch = getc(file1);
225*31207Smckusick }
226*31207Smckusick return num;
227*31207Smckusick }
228*31207Smckusick
readline()229*31207Smckusick readline()
230*31207Smckusick {
231*31207Smckusick
232*31207Smckusick dbg(readline);
233*31207Smckusick num1 = readnum();
234*31207Smckusick if (nextch == ',')
235*31207Smckusick num2 = readnum();
236*31207Smckusick else
237*31207Smckusick num2 = num1;
238*31207Smckusick lineact = nextch;
239*31207Smckusick }
240*31207Smckusick
skiptilleol()241*31207Smckusick skiptilleol()
242*31207Smckusick {
243*31207Smckusick
244*31207Smckusick dbg(skiptilleol);
245*31207Smckusick while (nextch != '\n')
246*31207Smckusick nextch = getc(file1);
247*31207Smckusick }
248*31207Smckusick
skiptilldot()249*31207Smckusick skiptilldot()
250*31207Smckusick {
251*31207Smckusick
252*31207Smckusick dbg(skiptilldot);
253*31207Smckusick do {
254*31207Smckusick if (fgets(linebuf, sizeof(linebuf), file1) == NULL) {
255*31207Smckusick fprintf(stderr, "error reading file1\n");
256*31207Smckusick exit(1);
257*31207Smckusick }
258*31207Smckusick } while (strcmp(linebuf, ".\n") != 0);
259*31207Smckusick }
260