home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i016: halign - line up columns (halign)
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: talcott!mcgill-vision!garfield!mouse (der Mouse)
- Mod.sources: Volume 6, Issue 16
- Archive-name: halign
-
- Here is a handy little program I wrote...it produces nicely lined-up
- columns from messy out-of-alignment columns. For example, it can turn
-
- 3 9
- 9 81
- 81 6561
- 6561 43046721
- 43046721 (overflow)
-
- into
-
- 3 9
- 9 81
- 81 6561
- 6561 43046721
- 43046721 (overflow)
-
- Read the man page for a full description.
-
- --------------------------------cut here--------------------------------
- #! /bin/sh
- #
- # Shar: Shell Archiver
- #
- # This archive created Wed Jun 11 04:53:03 1986
- # Run this through sh to create:
- # halign.1
- # halign.c
- echo x - halign.1 \(2051 characters\)
- sed 's/^X//' > halign.1 << \SHAR_EOF
- X.TH HALIGN 1 "11 June 1986"
- X.UC 4
- X.SH NAME
- Xhalign - produce lined-up columns
- X.SH SYNOPSIS
- X.nf
- X.ft B
- Xhalign [lrc][\fIn\fP] ...
- X.PP
- X.fi
- X.SH DESCRIPTION
- X\fIHalign\fP is a program to produce nicely lined-up columns from almost any
- Xsort of columnized input. For example, if you have a program which prints
- Xlines with two numbers on each line, halign can adjust things so they line up
- Xnicely. For example, let us suppose you have a program (here called `foo')
- Xwhich produces the following output:
- X.PP
- X.in +8
- X.nf
- X% foo
- X3 9
- X9 81
- X81 6561
- X6561 43046721
- X43046721 (overflow)
- X.PP
- X.fi
- XNow, to get things lined up and right-justified:
- X.PP
- X.in +8
- X.nf
- X% foo | halign r r
- X 3 9
- X 9 81
- X 81 6561
- X 6561 43046721
- X43046721 (overflow)
- X.PP
- X.fi
- XEach argument to halign must be a letter followed by an optional number. The
- Xletter specifies how the column is to be aligned; \fIl\fP specifies that the
- Xcolumn is to be set flush left, \fIr\fP indicates flush right, and \fIc\fP
- Xspecifies centering. Of course, centering cannot always be exact; if unable
- Xto center an entry exactly, halign will put the extra space on the right. If
- Xthe number is given, it is a minimum width for the column; normally, a column
- Xis only as wide as necessary to contain the widest entry in that column. For
- Xexample, \fIl10\fP specifies a column at least 10 characters wide (though it
- Xwill be wider if there is an entry wider than 10 characters), with the entry
- Xset at the left and padded on the right (if necessary).
- X.SH NOTES
- XHalign must of course read all of its input before printing anything; the
- Xinput is stored in files on /tmp (one file per column). Because these files
- Xare all kept open at once, halign will break if more than NFILE-3 (currently
- X17 on most UNIX systems) columns are specified.
- X.SH BUGS
- XHalign thinks control characters, such as backspace and escape, are normal
- Xprinting characters, so the columns may not line up if the entries contain
- Xsuch characters.
- X.SH AUTHOR
- Xder Mouse (Mike Parker, mcgill-vision!mouse), September, 1985.
- SHAR_EOF
- if test 2051 -ne "`wc -c halign.1`"
- then
- echo shar: error transmitting halign.1 \(should have been 2051 characters\)
- fi
- echo x - halign.c \(6462 characters\)
- sed 's/^X//' > halign.c << \SHAR_EOF
- X/*
- X * halign - program to produce lined-up columns
- X *
- X * Halign reads input in the form of columns of data separated by whitespace;
- X * the output is similar except that all the columns line up. This was
- X * inspired by the common uses of the \halign command in TeX; knowing how
- X * TeX's \halign command works will make this program almost self-evident.
- X *
- X * Usage is
- X *
- X * halign [clr][n] ...
- X *
- X * where each argument corresponds to one column in the input.
- X *
- X * The letter indicates how the column is to be justified; r indicates
- X * flush-right, l indicates flush-left, and c indicates centered. Of
- X * course, centering cannot be perfect without half-character resolution; if
- X * an item cannot be centered exactly the extra space will go on the right.
- X *
- X * The number n, if given, indicates a minimum width for the column. The
- X * default is to make the column just wide enough to contain the widest
- X * entry; if this entry is narrower than n the column will be n characters
- X * wide anyway.
- X *
- X * Halign always puts one space between columns on output.
- X *
- X * All adjusting is done with spaces; if tabs are desired pipe the output
- X * through /usr/ucb/unexpand -a.
- X *
- X * Examples:
- X *
- X * % cat x
- X * root 0 10 / /bin/csh
- X * mailer 0 10 / /bin/csh
- X * daemon 1 666 /
- X * uucp 66 1 /usr/spool/uucppublic /usr/lib/uucp/uucico
- X * wnj 8 10 /u1/guest/wnj /bin/csh
- X * mckusick 9 10 /u1/guest/mckusick /bin/csh
- X * % halign l l l l l < x
- X * root 0 10 / /bin/csh
- X * mailer 0 10 / /bin/csh
- X * daemon 1 666 /
- X * uucp 66 1 /usr/spool/uucppublic /usr/lib/uucp/uucico
- X * wnj 8 10 /u1/guest/wnj /bin/csh
- X * mckusick 9 10 /u1/guest/mckusick /bin/csh
- X * % halign l r5 r5 c c < x
- X * root 0 10 / /bin/csh
- X * mailer 0 10 / /bin/csh
- X * daemon 1 666 /
- X * uucp 66 1 /usr/spool/uucppublic /usr/lib/uucp/uucico
- X * wnj 8 10 /u1/guest/wnj /bin/csh
- X * mckusick 9 10 /u1/guest/mckusick /bin/csh
- X *
- X * Halign must of course read to the end of its input before generating any
- X * output, so that it knows how wide the columns must be. The input column
- X * entries are copied into temporary files (on /tmp).
- X *
- X * The current incarnation cannot deal with more than about 17 columns; this
- X * is because a separate temporary file is used for each column, so not more
- X * than NFILE-3 (3 for stdin/stdout/stderr) columns will work.
- X *
- X * Copyright 1985 by Mike Parker. Permission is granted for redistribution
- X * of this code, or modified versions of it, for any purpose as long as this
- X * notice remains intact and that no additional restrictions are placed on
- X * further redistribution. I have tried to make sure that this program
- X * functions as the above description indicates, but I make no guarantees
- X * that this code does anything useful, or even that it does not do anything
- X * harmful.
- X *
- X * If you find any bugs I would appreciate hearing, especially if you also
- X * fix them. Write to
- X * {ihnp4,decvax,akgua,utzoo,etc}!utcsri!mcgill-vision!mouse
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/file.h>
- X
- Xchar *malloc();
- Xchar *realloc();
- X#define NEW(type) ((type *) malloc(sizeof(type)))
- X#define OLD(x) free((char *) x)
- X
- Xchar **argvec;
- X
- Xtypedef struct _spec {
- X char spec;
- X int tfd;
- X FILE *tf;
- X char *buf;
- X int maxwidth; } SPEC;
- X
- Xint errs;
- Xint ncols;
- Xint nlines;
- XSPEC *spec;
- Xchar tfilename[80];
- X
- Xmain(ac,av)
- Xint ac;
- Xchar **av;
- X{
- X int i;
- X int j;
- X int k;
- X char *cp;
- X char *dp;
- X char c;
- X int inspace;
- X int colwidth;
- X
- X argvec = av;
- X errs = 0;
- X ncols = ac - 1;
- X if (ncols <= 0)
- X { fprintf(stderr,"Usage: %s [clr][n] [clr][n] ...\n",argvec[0]);
- X exit(1);
- X }
- X spec = (SPEC *) malloc(ncols*sizeof(SPEC));
- X sprintf(tfilename,"/tmp/halign.%d",getpid());
- X av ++;
- X for (i=0;i<ncols;i++)
- X { spec[i].maxwidth = 0;
- X switch (av[i][0])
- X { case 'c':
- X case 'l':
- X case 'r':
- X if (av[i][1])
- X { spec[i].maxwidth = atoi(av[i]+1);
- X }
- X spec[i].spec = av[i][0];
- X unlink(tfilename);
- X spec[i].tfd = open(tfilename,O_RDWR|O_CREAT|O_TRUNC,0644);
- X unlink(tfilename);
- X if (spec[i].tfd < 0)
- X { fprintf(stderr,"%s: cannot open temporary file %s: ",
- X argvec[0],tfilename);
- X perror(0);
- X errs ++;
- X }
- X break;
- X default:
- X fprintf(stderr,
- X "%s: `%c' is not a valid specification (c, l, or r)\n",
- X argvec[0],av[i][0]);
- X errs ++;
- X break;
- X }
- X }
- X for (i=0;i<ncols;i++)
- X { if (spec[i].tfd >= 0)
- X { spec[i].tf = fdopen(spec[i].tfd,"r+");
- X if (! spec[i].tf)
- X { fprintf(stderr,"%s: cannot fdopen, serious failure: ",argvec[0]);
- X perror(0);
- X errs ++;
- X }
- X }
- X }
- X if (errs)
- X { exit(1);
- X }
- X nlines = 0;
- X i = 0;
- X inspace = 1;
- X colwidth = 0;
- X while (1)
- X { c = getchar();
- X if (feof(stdin))
- X { if ((i > 0) || (colwidth > 0))
- X { c = '\n';
- X }
- X else
- X { break;
- X }
- X }
- X else if (isspace(c))
- X { if (! inspace)
- X { inspace = 1;
- X if (colwidth > spec[i].maxwidth)
- X { spec[i].maxwidth = colwidth;
- X }
- X if (i < ncols-1)
- X { putc('\n',spec[i].tf);
- X i ++;
- X }
- X colwidth = 0;
- X }
- X if (c == '\n')
- X { for (;i<ncols;i++)
- X { putc('\n',spec[i].tf);
- X }
- X nlines ++;
- X i = 0;
- X colwidth = 0;
- X inspace = 1;
- X }
- X }
- X else
- X { putc(c,spec[i].tf);
- X colwidth ++;
- X inspace = 0;
- X }
- X }
- X for (i=0;i<ncols;i++)
- X { fseek(spec[i].tf,0L,0);
- X spec[i].buf = malloc(spec[i].maxwidth+2);
- X }
- X for (;nlines>0;nlines--)
- X { for (i=0;i<ncols;i++)
- X { fgets(spec[i].buf,spec[i].maxwidth+2,spec[i].tf);
- X j = strlen(spec[i].buf);
- X if (j > 0)
- X { spec[i].buf[--j] = '\0';
- X }
- X k = spec[i].maxwidth - j;
- X cp = spec[i].buf;
- X cp[spec[i].maxwidth] = '\0';
- X spacefill(cp+j,k);
- X switch (spec[i].spec)
- X { case 'l':
- X break;
- X case 'c':
- X k /= 2;
- X /* fall through */
- X case 'r':
- X cp += j;
- X dp = cp + k;
- X for (;j>0;j--)
- X { *--dp = *--cp;
- X }
- X for (;k>0;k--)
- X { *--dp = ' ';
- X }
- X break;
- X }
- X if (i)
- X { putchar(' ');
- X }
- X fputs(spec[i].buf,stdout);
- X }
- X putchar('\n');
- X }
- X}
- X
- Xspacefill(ptr,nb)
- Xregister char *ptr;
- Xregister int nb;
- X{
- X for (;nb>0;nb--)
- X { *ptr++ = ' ';
- X }
- X}
- SHAR_EOF
- if test 6462 -ne "`wc -c halign.c`"
- then
- echo shar: error transmitting halign.c \(should have been 6462 characters\)
- fi
- exit 0
- # end of shell archive
-
-
-