#! /usr/bin/gawk -f
# Last edited on 2000-02-02 02:27:56 by stolfi
BEGIN {
usage = ( ARGV[0] "\\\n" \
" [-v columns=COLUMNS | -v pagewidth=PAGEWIDTH] \\\n" \
" [-v colwidth=COLWIDTH] \\\n" \
" [-v lines=LINES] \\\n" \
" [-v sep='string'] \\\n" \
" [-v filler='string'] \\\n" \
" [-v left='string'] [-v right='string'] \\\n" \
" [-v head='string'] [-v foot='string'] \\\n" \
" < INFILE > OUTFILE" \
);
# Like "pr" (bleech!) but does the right thing. Prints INFILE in
# COLUMNS columns, LINES lines per page.
# The columns in the last page are always balanced. If LINES is 0 or
# omitted, it defaults to infinity, i.e. there will be a single page
# with just enough lines to fit balanced columns. Otherwise
# all pages (even the last one) will have LINES lines of data.
# The FILLER string is used to complete short columns, and,
# if LINES > 0, to complete the last page. It defaults to empty.
# If COLWIDTH is not specified, it defaults to 0. The actual width
# of each column is the maximum between COLWIDTH, the length of
# the the widest line in INFILE, and the length of the FILLER string.
# If PAGEWIDTH and COLUMNS are not specified or zero, they default to
# infinity. At least one of them must be specified. In any case,
# COLUMNS will be reduced as needed so that the output lines will not
# exceed the specified PAGEWIDTH. On the other hand, at least
# one column will be printed, even if the PAGEWIDTH gets exceeded.
abort = -1;
if (columns == "")
{ columns = 0; }
else if ((columns !~ /^[0-9]+$/) || (columns < 0))
{ arg_error("bad \"columns\""); }
if (pagewidth == "")
{ pagewidth = 0; }
else if ((pagewidth !~ /^[0-9]+$/) || (pagewidth < 0))
{ arg_error("bad \"pagewidth\""); }
if ((pagewidth == 0) && (columns == 0))
{ arg_error("you must specify \"pagewidth\" or \"columns\""); }
if (lines == "")
{ lines = 0; }
else if ((lines !~ /^[0-9]+$/) || (lines < 0))
{ arg_error("bad \"lines\""); }
if (colwidth == "")
{ colwidth = 0; }
else if ( colwidth !~ /^[0-9]+$/ )
{ arg_error("bad \"colwidth\""); }
nrecs = 0;
maxwidth = length(filler);
if (colwidth > maxwidth) { maxwidth = colwidth; }
split("", rec);
}
# Gobble up lines
(abort >= 0) { exit abort; }
// {
rec[nrecs] = $0;
nrecs++;
m = length($0); if (m > maxwidth) { maxwidth = m; maxline = $0; }
}
END {
if (abort >= 0) { exit abort; }
# printf "maxwidth = %d maxline = [%s]\n", maxwidth, maxline;
# Adjust number of columns to fit:
if (columns == 0) { columns = nrecs; }
cw = maxwidth + length(sep);
if ((cw > 0) && (pagewidth != 0))
{ avail = pagewidth - length(left) - length(right);
maxcols = int((avail + length(sep)) / cw);
if (maxcols < columns) { columns = maxcols; }
}
if (columns == 0) { columns = 1; }
# Adjust page size and number of pages:
if (lines > 0)
{ nrecspp = lines*columns;
npages = int((nrecs + nrecspp - 1)/ nrecspp);
}
else
{ nrecspp = nrecs;
lines = int((nrecspp + columns - 1) / columns);
npages = 1;
}
# Print it:
for (ip = 0; ip < npages; ip++)
{
if (head != "") { printf "%s\n", head; }
# Compute range and number of records in this page:
ini = ip*nrecspp;
fin = ini + nrecspp;
if (fin > nrecs) { fin = nrecs + 1;}
nr = (fin - ini);
# Compute number of records per column:
nrpc = int((nr + columns - 1) / columns);
for (jl = 0; jl < lines; jl++)
{ printf "%s", left;
for (kc = 0; kc < columns; kc++)
{ if (kc > 0) { printf "%s", sep; }
if (jl < nrpc)
{ ir = ip*nrecspp + kc*nrpc + jl;
r = ( ir < nrecs ? rec[ir] : filler );
}
else
{ r = filler; }
printf "%-*s", maxwidth, r;
}
printf "%s\n", right;
}
if (foot != "") { printf "%s\n", foot; }
}
}
function arg_error(msg)
{
printf "*** %s\n", msg > "/dev/stderr";
abort = 1;
exit abort;
}