comm.c

Go to the documentation of this file.
00001 /* comm - select lines from two sorted files    Author: Martin C. Atkins */
00002 
00003 /*
00004  *      This program was written by:
00005  *              Martin C. Atkins,
00006  *              University of York,
00007  *              Heslington,
00008  *              York. Y01 5DD
00009  *              England
00010  *      and is released into the public domain, on the condition
00011  *      that this comment is always included without alteration.
00012  */
00013 
00014 #include <sys/types.h>
00015 #include <fcntl.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <unistd.h>
00019 #include <minix/minlib.h>
00020 #include <stdio.h>
00021 
00022 #define BUFFER_SIZE (512)
00023 #define LINMAX (600)
00024 
00025 struct file {
00026   char *name;                   /* the file's name */
00027   int fd;                       /* the file descripter */
00028   char buf[BUFFER_SIZE];                /* buffer storage */
00029   char *next;                   /* the next character to read */
00030   char *endp;                   /* the first invalid character */
00031   int seeneof;                  /* an end of file has been seen */
00032 } files[2];
00033 
00034 char lines[2][LINMAX];
00035 
00036 int colflgs[3] = {1, 2, 3};     /* number of tabs + 1: 0 => no column */
00037 
00038 static char *umsg = "Usage: comm [-[123]] file1 file2\n";
00039 
00040 _PROTOTYPE(int main, (int argc, char **argv));
00041 _PROTOTYPE(void usage, (void));
00042 _PROTOTYPE(void error, (char *s, char *f));
00043 _PROTOTYPE(void eopen, (char *fn, struct file *file));
00044 _PROTOTYPE(int getbuf, (struct file *file));
00045 _PROTOTYPE(int readline, (int fno));
00046 _PROTOTYPE(void comm, (void));
00047 _PROTOTYPE(void putcol, (int col, char *buf));
00048 _PROTOTYPE(void cpycol, (int col));
00049 
00050 int main(argc, argv)
00051 int argc;
00052 char *argv[];
00053 {
00054   int cnt;
00055   if (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
00056         char *ap;
00057         for (ap = &argv[1][1]; *ap; ap++) switch (*ap) {
00058                     case '1':
00059                     case '2':
00060                     case '3':
00061                         cnt = *ap - '1';
00062                         if (colflgs[cnt] == 0) break;
00063                         colflgs[cnt] = 0;
00064                         for (cnt++; cnt < 3; cnt++) colflgs[cnt]--;
00065                         break;
00066                     default:    usage();
00067                 }
00068         argc--;
00069         argv++;
00070   }
00071   if (argc != 3) usage();
00072   eopen(argv[1], &files[0]);
00073   eopen(argv[2], &files[1]);
00074   comm();
00075   return(0);
00076 }
00077 
00078 void usage()
00079 {
00080 
00081   std_err(umsg);
00082   exit(1);
00083 }
00084 
00085 void error(s, f)
00086 char *s, *f;
00087 {
00088   std_err("comm: ");
00089   std_err(s);
00090   if (f) std_err(f);
00091   std_err("\n");
00092   exit(1);
00093 }
00094 
00095 void eopen(fn, file)
00096 char *fn;
00097 struct file *file;
00098 {
00099   file->name = fn;
00100   file->next = file->endp = &file->buf[0];
00101   file->seeneof = 0;
00102   if (fn[0] == '-' && fn[1] == '\0')
00103         file->fd = 0;
00104   else if ((file->fd = open(fn, O_RDONLY)) < 0)
00105         error("can't open ", fn);
00106 }
00107 
00108 
00109 int getbuf(file)
00110 struct file *file;
00111 {
00112 /* Get a buffer-full from the file.  Return true if no characters
00113  * were obtained because we are at end of file.
00114  */
00115   int n;
00116 
00117   if (file->seeneof) return(1);
00118   if ((n = read(file->fd, &file->buf[0], BUFFER_SIZE)) < 0)
00119         error("read error on ", file->name);
00120   if (n == 0) {
00121         file->seeneof++;
00122         return 1;
00123   }
00124   file->next = &file->buf[0];
00125   file->endp = &file->buf[n];
00126   return(0);
00127 }
00128 
00129 
00130 int readline(fno)
00131 int fno;
00132 {
00133 /* Read up to the next '\n' character to buf.
00134  * Return a complete line, even if end of file occurs within a line.
00135  * Return false at end of file/
00136  */
00137   register struct file *file = &files[fno];
00138   char *buf = lines[fno];
00139 
00140   if (file->next == file->endp && getbuf(file)) return(0);
00141   while ((*buf++ = *file->next++) != '\n')
00142         if (file->next == file->endp && getbuf(file)) {
00143                 *buf++ = '\n';
00144                 *buf = '\0';
00145                 return(1);
00146         }
00147   *buf = '\0';
00148   return(1);
00149 }
00150 
00151 void comm()
00152 {
00153   register int res;
00154 
00155   if (!readline(0)) {
00156         cpycol(1);
00157         return;
00158   }
00159   if (!readline(1)) {
00160         putcol(0, lines[0]);
00161         cpycol(0);
00162         return;
00163   }
00164   for (;;) {
00165         if ((res = strcmp(lines[0], lines[1])) != 0) {
00166                 res = res > 0;
00167                 putcol(res, lines[res]);
00168                 if (!readline(res)) {
00169                         putcol(!res, lines[!res]);
00170                         cpycol(!res);
00171                         return;
00172                 }
00173         } else {
00174                 putcol(2, lines[0]);    /* files[1]lin == f2lin */
00175                 if (!readline(0)) {
00176                         cpycol(1);
00177                         return;
00178                 }
00179                 if (!readline(1)) {
00180                         putcol(0, lines[0]);
00181                         cpycol(0);
00182                         return;
00183                 }
00184         }
00185   }
00186 
00187   /* NOTREACHED */
00188 }
00189 
00190 void putcol(col, buf)
00191 int col;
00192 char *buf;
00193 {
00194   int cnt;
00195 
00196   if (colflgs[col] == 0) return;
00197   for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
00198   printf("%s", buf);
00199 }
00200 
00201 void cpycol(col)
00202 int col;
00203 {
00204   if (colflgs[col]) while (readline(col))
00205                 putcol(col, lines[col]);
00206 }

Generated on Fri Apr 14 22:57:04 2006 for minix by  doxygen 1.4.6