date and time created 87/05/25 13:38:53 by mckusick
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Tue, 26 May 1987 04:38:53 +0000 (20:38 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Tue, 26 May 1987 04:38:53 +0000 (20:38 -0800)
SCCS-vsn: local/local.cmd/chgbars.c 5.1

usr/src/local/local.cmd/chgbars.c [new file with mode: 0644]

diff --git a/usr/src/local/local.cmd/chgbars.c b/usr/src/local/local.cmd/chgbars.c
new file mode 100644 (file)
index 0000000..eefa0a2
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)chgbars.c  5.1 (Berkeley) %G%";
+#endif not lint
+
+/*
+ * Derived from original program by A. Dain Samples.
+ * 
+ * The program chgbars will accept the output from a diff comparison of
+ * two versions of a file.  It will then read the new version of the file
+ * and insert the appropriate troff commands to put change bars in the
+ * right margin. Typing 'chgbars' without any arguments will give you
+ * some documentation and an example.
+ * 
+ * Caveat: If you make a change inside an equation or table, the
+ * preprocessors eqn and tbl may not like what chgbars does to the file.
+ * You may have to go into the output from chgbars to remove or rearrange
+ * some of the lines of the form '.mc |  \"open' or '.mc  \"close' in
+ * order to get through tbl or eqn.
+ * 
+ * Unfortunately, users of RCS will be disappointed: one cannot use rcsdiff.
+ * Rcsdiff compares the files in the wrong order.
+ * 
+ * There is a relatively easy way to do the job with the tools sed and awk.
+ * However, sed does not allow enough commands to process large documents.
+ * In the true spirit of a filter/tool, chgbars is limited only by the
+ * amount of memory on the machine, and is fast and useful.
+ * 
+ * The modifications necessary are outlined:
+ * 
+ * FORM OF DIFF OUTPUT COMMENT                 NEW SED COMMANDS
+ * ================================================================
+ * 100a                        means those lines       100a\\
+ * L1                  were deleted from       .mc |\\
+ * L2                  oldfile                 .mc
+ * :
+ * Ln
+ * .
+ * ----------------------------------------------------------------
+ * 100c                        
+ * L1          
+ * L2  
+ * : 
+ * Ln                                          
+ * .
+ *     means that line 100 in newfile replaced all those lines in oldfile.
+ *             100a
+ *             .mc
+ *             99 a
+ *             .mc |
+ * ----------------------------------------------------------------
+ * 100d                        that line was added     100a\\
+ *                     to oldfile              .mc
+ *                                             99a\\
+ *                                             .mc |
+ * ----------------------------------------------------------------
+ * 100,200d            those lines were        200a\\
+ *                     added to oldfile                .mc
+ *                                             99a\\
+ *                                             .mc |
+ * ----------------------------------------------------------------
+ * 100,200c            
+ * L1          
+ * L2  
+ * :
+ * Ln
+ * .
+ *     means lines 100 to 200 of newfile replaced all the following lines
+ *     in oldfile.
+ *             200a
+ *             .mc
+ *             99a
+ *             .mc |
+ * ----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+
+#define dbg(s)  /* fprintf(stderr,"s\n") */
+#define none 0
+#define open 1
+#define close 2
+#define both 3
+
+char (*action)[];
+FILE *file1, *file2;
+char linebuf[1024];
+char nextch;
+int num1, num2, t, line;
+char lineact;
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1986 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char  *p;
+       register int    i;
+
+       if (argc < 2)
+               usage();
+       /* open $1 */
+       if (strcmp(argv[1], "-") == 0) {
+               file1 = stdin;
+               if (argc <= 2)
+                       usage();
+       } else if ((file1 = fopen(argv[1], "r")) == NULL) {
+               fprintf(stderr, "error: can't open %s\n", argv[1]);
+               exit(1);
+       }
+       /*
+        * read each entry setting the appropriate entry in action[]
+        *
+        * get the first line number: since diff -e puts the numbers out
+        * in reverse order, this tells us how big to make the file
+        */
+       readline();
+       if (lineact == 'a')
+               t = num1;
+       else
+               t = num2;
+       action = (char (*)[]) malloc(t + 1);
+       for (p = (char *) action, i = 0; i < t; i++)
+               *p++ = (char) none;
+       while (!feof(file1)) {
+               if (lineact == 'a') {
+                       (*action)[num1] = both;
+                       skiptilldot();
+               } else {
+                       (*action)[num1 - 1] = open;
+                       (*action)[num2] = close;
+                       if (lineact == 'c')
+                               skiptilldot();
+                       else
+                               skiptilleol();
+               }
+               readline();
+       }
+       fclose(file1);
+       /* open $2 */
+       if (argc == 2)
+               file2 = stdin;
+       else
+               file2 = fopen(argv[2], "r");
+       if (file2 == NULL) {
+               fprintf(stderr, "can't open %2\n", argv[2]);
+               exit(1);
+       }
+       line = 0;
+       while (!feof(file2)) {
+               if (line != 0)
+                       fputs(linebuf, stdout);
+               if (line <= t) {
+                       switch ((*action)[line]) {
+                       case open:
+                               printf(".mc |   \\\"open\n");
+                               break;
+                       case close:
+                               printf(".mc     \\\"close\n");
+                               break;
+                       case both:
+                               printf(".mc |   \\\"both\n");
+                               printf(".mc\n");
+                               break;
+                       default:;
+                       }
+               }
+               fgets(linebuf, sizeof(linebuf), file2);
+               line++;
+       }
+       if (line <= t) {
+               fprintf(stderr, "oops: number of lines read does not match\n");
+               fprintf(stderr, "number of lines expected\n");
+               exit(1);
+       }
+       exit(0);
+}
+
+usage()
+{
+
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\tchgbars diff.out\n");
+       fprintf(stderr, "\t\t\treads the output from diff, and expects the\n");
+       fprintf(stderr, "\t\t\tfile to be modified on stdin\n");
+       fprintf(stderr, "\tchgbars diff.out file.tbm\n");
+       fprintf(stderr, "\t\t\tboth the output from diff and the file to be\n");
+       fprintf(stderr, "\t\t\tmodified are stated explicitly\n");
+       fprintf(stderr, "\tchgbars - file.tbm\n");
+       fprintf(stderr, "\t\t\treads the output from diff on stdin\n");
+       fprintf(stderr, "\nE.g.\n");
+       fprintf(stderr, "diff -b -e newfile oldfile | chgbars - newfile | vtroff -ms\n");
+       fprintf(stderr, "\t(note the order of the files in the diff command!)\n");
+       fprintf(stderr, "\n\nBe forewarned: chgbars does not know about tables or equations.\n");
+       fprintf(stderr, "If any part of a table or equation is changed, chgbars will insert the\n");
+       fprintf(stderr, ".mc commands, whether tbl or eqn likes it or not.\n");
+       fprintf(stderr, "This means that you may have to do some hand editing of the output of\n");
+       fprintf(stderr, "chgbars to make it acceptable to one or both of these preprocessors.\n");
+
+       exit(1);
+}
+
+readnum()
+{
+       int num;
+
+       dbg(readnum);
+       num = 0;
+       nextch = getc(file1);
+       while (isdigit(nextch)) {
+               num = num * 10 + nextch - '0';
+               nextch = getc(file1);
+       }
+       return num;
+}
+
+readline()
+{
+
+       dbg(readline);
+       num1 = readnum();
+       if (nextch == ',')
+               num2 = readnum();
+       else
+               num2 = num1;
+       lineact = nextch;
+}
+
+skiptilleol()
+{
+
+       dbg(skiptilleol);
+       while (nextch != '\n')
+               nextch = getc(file1);
+}
+
+skiptilldot()
+{
+
+       dbg(skiptilldot);
+       do {
+               if (fgets(linebuf, sizeof(linebuf), file1) == NULL) {
+                       fprintf(stderr, "error reading file1\n");
+                       exit(1);
+               }
+       } while (strcmp(linebuf, ".\n") != 0);
+}