home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume16
/
colm
next >
Wrap
Text File
|
1989-01-17
|
34KB
|
1,145 lines
Subject: v16i087: A columnation program
Newsgroups: comp.sources.unix
Approved: rsalz@uunet.UU.NET
Submitted-by: Gary Oberbrunner <masscomp!garyo>
Posting-number: Volume 16, Issue 87
Archive-name: colm
I got sick of the fact that ls(1) will sort its columns down when given
no arguments, but not in any other case. And I figured the world needed
a decent columnation tool. So here is one I just whipped up; it does
fixed and variable width columns, selectable gutter widths, it automatically
figures out how many columns to use (unlike pr -#), and it allows various
formatting options such as selectable leader character, selectable tabbing
with selectable tab size, and your choice of leaders or a separation string.
Colm should compile on any machine that has getopt(3C).
The hooks are in there for multi-page columnation, but it's not done yet.
Any volunteers?
A man page is included. To make, unpack the shar and type 'make'. Enjoy!
----------------------------------------------------------------------------
Remember, Truth is not beauty; (617)692-6200x2445
Information is not knowledge; Beauty is not love; Gary Oberbrunner
Knowledge is not wisdom; Love is not music; ...!masscomp!garyo
Wisdom is not truth; Music is the best. - FZ ....garyo@masscomp
#--------------------------------- cut here ----------------------------------
# To unpack, cut out all lines above the dotted line, and any lines
# after the similar line near the end of the file.
# Then run the remaining file with /bin/sh (NOT /bin/csh) in the
# appropriate directory. It will create the following files:
#
# colm.1
# makefile
# colm.h
# std.h
# colm.c
# column.c
# lists.c
# output.c
# readin.c
# vcolumn.c
#########################################################
if (test -d colm.1) then
echo colm.1 is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f colm.1) then
echo 'Should I overwrite the existing version of colm.1 (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f colm.1) then
echo Overwriting colm.1...
else
echo Creating colm.1...
fi
sed 's/-//;s/%$//' << 'END.colm.1' > colm.1
-.\"@(#)colm.1 1.1 6/3/88 22:48:54%
-.RL "MASSCOMP"%
-.TH LS 1%
-.UC%
-.SH NAME%
-colm \- columnate lines of text%
-.SH SYNOPSIS%
-.B colm%
-[%
-.B -cglnstvwLT%
-] name ...%
-.SH DESCRIPTION%
-.I colm%
-produces multi-column output from single-column input.%
-It is sort of a cross between%
-.I pr%
--<n> (which prints multi-column output sorted across)%
-and the column-sorting function%
-of%
-.I ls%
-(1) (which sorts down, but only if given no filename arguments).%
-It can produce fixed or variable width columns, and it figures out any%
-options not explicitly specified.%
-.PP%
-.I colm%
-uses getopt(3C) to parse its options, so options may be strung%
-together, as in%
-.IR -vw ,%
-and values may either adhere to their option letters or follow as%
-the next argument.%
-The options are as follows:%
-.TP%
-.B \-v%
-Produce variable-width columns.%
-.I colm%
-uses an iterative algorithm to find the maximum number of columns that%
-allows at least the gutter-width between the widest element and the next%
-column.%
-The -v option is incompatible with -c.%
-.TP%
-.BI \-c n%
-Use fixed-width columns of width%
-.IR n .%
-Data will be truncated if necessary to fit the specified column width.%
-If%
-.B -c%
-is not used,%
-.I colm%
-expands the column width(s) to fit the output width.%
-.TP%
-.BI \-g n%
-Use a "gutter" of%
-.I n%
-characters between columns.%
-The default is 1.%
-.TP%
-.BI \-n n%
-Use%
-.I n%
-fixed-width columns.%
-Without%
-.BR -n ,%
-.I colm%
-fits as many columns in the given output width as it can.%
-.TP%
-.B -s%
-Spread the columns to fit the output width.%
-Otherwise columns are made as narrow as possible,%
-while leaving the gutter space between columns.%
-With fixed-width columns, the columns will be spread as far as%
-possible while keeping their widths even.%
-WIth variable-width columns, the columns will be spread so that there%
-is an even amount of white space between them.%
-.TP%
-.BI \-w n%
-Sets the output width to%
-.I n%
-characters.%
-The output lines may be shorter, but cannot be longer than%
-.IR n .%
-.TP%
-.BI \-l n%
-Sets the page length to%
-.I n%
-lines.%
-This option is not implemented.%
-An error message will result if you try to use it.%
-.TP%
-.BI \-L c%
-Sets the%
-.I leader character%
-to%
-.IR c .%
-This character is used repeatedly to fill in the space between columns.%
-The default is to use as many spaces and tabs as are needed.%
--L ' ' will cause%
-.I colm%
-not to use tabs.%
-Watch out for shell metacharacters.%
-.TP%
-.BI \-t s%
-Use the literal string "s" to separate the columns,%
-rather than a repeated leader character.%
-Watch out for shell metacharacters.%
-.br%
-There are two main differences between -L and -t:%
--L only allows a single character, while -t allows a string;%
-and the leader character specified by -L is repeated to fill the%
-space, whereas the string specified with -t is used only once between%
-columns.%
-Generally, -t will not produce even columns, while -L always will.%
-.TP%
-.BI \-T n%
-Specifies the output tab width as%
-.I n%
-characters.%
-The default is eight.%
-.SH DIAGNOSTICS%
-Several errors and warnings can be produced by%
-.IR colm :%
-.br%
-A usage message is produced for illegal options.%
-.br%
-If any single input line is longer than the output width,%
-.I colm%
-terminates with an error.%
-.br%
-Illegal combinations of arguments and impossible conditions,%
-such as 20 columns of 30 characters%
-in an output width of 79 columns, or selecting spreading with a fixed%
-separator string, cause errors.%
-.br%
-Certain combinations of total number of lines and specified number of%
-columns cannot produce balanced columns, even with the last column%
-allowed to be short.%
-If this occurs,%
-.I colm%
-prints an explanatory message on stderr and uses a smaller number%
-of columns than were specified.%
-.br%
-Attempting to do multi-page columnation (with -l) produces an error.%
-.br%
-Nonexistent or unreadable files produce an error.%
-.SH SEE ALSO%
-pr(1), ls(1)%
-.SH BUGS%
-Multi-page columnation is not implemented.%
-.XX "Text manipulation"%
-.XX "Columns, creating"%
END.colm.1
if (test -d makefile) then
echo makefile is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f makefile) then
echo 'Should I overwrite the existing version of makefile (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f makefile) then
echo Overwriting makefile...
else
echo Creating makefile...
fi
sed 's/-//;s/%$//' << 'END.makefile' > makefile
-#%
-# Makefile for colm - auto-columnation filter%
-# 5-31-88%
-#%
-SCCSID="@(#)makefile 1.1 6/3/8822:49:03"%
-CFLAGS=-g -I/usr/garyo/lib%
-LIBS=%
-LDFLAGS=-g%
-OBJECTS = colm.o lists.o column.o vcolumn.o readin.o output.o%
-%
-colm: $(OBJECTS)%
- cc $(LDFLAGS) -o $@ $(OBJECTS) $(LIBS)%
-%
-$(OBJECTS): colm.h%
END.makefile
if (test -d colm.h) then
echo colm.h is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f colm.h) then
echo 'Should I overwrite the existing version of colm.h (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f colm.h) then
echo Overwriting colm.h...
else
echo Creating colm.h...
fi
sed 's/-//;s/%$//' << 'END.colm.h' > colm.h
-/*----------------------------------------------------------------------%
- * Header file for auto-columnator%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- * SCCS ID: @(#)colm.h 1.1 6/3/88 22:47:12%
- *----------------------------------------------------------------------%
- */%
-%
-#define MAX_COLS 1000 /* maximum number of columns */%
-%
-#define TRUE 1%
-#define FALSE 0%
-%
-typedef int BOOLEAN;%
-%
-/* A doubly-linked list of text lines */%
-typedef struct NODE {%
- struct NODE *next;%
- struct NODE *prev;%
- int length;%
- char *string;%
-} NODE;%
-%
-extern NODE *findn();%
-%
-extern NODE Lines; /* the head of the list */%
- /* defined in lists.c */%
-%
-extern int TotalLines; /* total # of lines read */%
- /* defined in readin.c */%
-%
-/* Command-line options: */%
-typedef struct OPTS {%
- int Vflg; /* variable col width */%
- int Sflg; /* stretch output columns to fit */%
- int Gutter; /* blank space between columns */%
- int ColWidth; /* fixed col width */%
- int Ncols; /* number of cols */%
- int Width; /* output width */%
- int PageLen; /* page length */%
- int Tabsize; /* tab size (normally 8) */%
- char ColSep[100]; /* separator string */%
- char Leader; /* leader char for column separation */%
-} OPTS;%
-%
-extern OPTS Opts; /* defined in colm.c */%
END.colm.h
if (test -d std.h) then
echo std.h is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f std.h) then
echo 'Should I overwrite the existing version of std.h (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f std.h) then
echo Overwriting std.h...
else
echo Creating std.h...
fi
sed 's/-//;s/%$//' << 'END.std.h' > std.h
-/* Standard include file with lots of generally useful stuff */%
-/* Copyright c. 1988, Gary Oberbrunner. */%
-/* This program may be freely redistributed providing that this source code */%
-/* and the accompanying copyright notice are preserved intact. */%
-/* SCCS Id: @(#)std.h 1.2 1/21/88 19:03:14 */%
-%
-#define STDIN 0%
-#define STDOUT 1%
-#define STDERR 2%
-%
-#define min(x,y) ((x) < (y) ? (x) : (y))%
-#define max(x,y) ((x) > (y) ? (x) : (y))%
-#define clamp(x, mn, mx) (((x) <= (mn)) ? (mn) : (((x) >= (mx)) ? (mx) : (x)))%
-%
-#define SECURITY%
-#ifdef SECURITY%
-#define ASSERT(exp) { if (!(exp)) { fprintf(stderr,\%
- "Assertion error: %s, line %d. Assertion exp failed.\n",\%
- __FILE__, __LINE__);\%
- exit(69); } }%
-#else%
-#define ASSERT(exp)%
-#endif%
-%
-#define dbug0(str) \%
- if (debug) fprintf(stderr, str);%
-#define dbug1(str, arg1) \%
- if (debug) fprintf(stderr, str, arg1);%
-#define dbug2(str, arg1, arg2) \%
- if (debug) fprintf(stderr, str, arg1, arg2);%
-#define dbug3(str, arg1, arg2, arg3) \%
- if (debug) fprintf(stderr, str, arg1, arg2, arg3);%
-#define dbug4(str, arg1, arg2, arg3, arg4) \%
- if (debug) fprintf(stderr, str, arg1, arg2, arg3, arg4);%
-%
-extern char *malloc();%
-/*%
- * NEW is a macro to malloc 'n' new variables of type 'type'.%
- */%
-#define NEW(var, type, num) \%
- if ((var = (type *) malloc((num) * sizeof(type)))==NULL) \%
- { fprintf(stderr,\%
- "ERROR: Out of memory.\nLast request:\n");\%
- fprintf(stderr,\%
- "\tNumber: num\n\tType : type\n\tName : var.\n");\%
- fprintf(stderr,"File %s, line %d\n", __FILE__, __LINE__);\%
- fprintf(stderr,\%
- "\tTotal requested: num=%d x sizeof(type)=%d\n\t =%d bytes.\n",\%
- num, sizeof(type), (num) * sizeof(type));\%
- exit(99); }%
END.std.h
if (test -d colm.c) then
echo colm.c is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f colm.c) then
echo 'Should I overwrite the existing version of colm.c (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f colm.c) then
echo Overwriting colm.c...
else
echo Creating colm.c...
fi
sed 's/-//;s/%$//' << 'END.colm.c' > colm.c
-/*----------------------------------------------------------------------%
- * colm: auto-columnate, with various options.%
- * by Gary Oberbrunner 5-31-88%
- *%
- * -v variable-width columns (default: fixed-width)%
- * -s spread output columns to fit output width (default: don't)%
- * -g # Separate columns by a #-column gutter%
- * -c # column width (size) (default: max line length of input)%
- * -n # use # columns (default: program picks max # that will fit)%
- * -w # output width is # characters/line (default: 80)%
- * -l # page length is # lines (default: infinite)%
- * -L c leader character is 'c' (default: space)%
- * -t s use string "s" as separator; (default: enough space to line up)%
- * -T # tab size # chars (default 8)%
- *%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- *----------------------------------------------------------------------%
- */%
-%
-#include <stdio.h>%
-#include "std.h"%
-#include "colm.h"%
-%
-int debug = 1;%
-static char SCCSId[] = "@(#)colm.c 1.2 6/3/88 (MASSCOMP) 23:17:12";%
-static char Copyright[] = "Copyright c. 1988, Gary Oberbrunner.";%
-%
-OPTS Opts; /* global copy of original options */%
-main (argc, argv)%
-int argc;%
-char **argv;%
-{%
- int c;%
- extern int optind;%
- extern char *optarg;%
- int errflg = 0;%
- int totlines = 0;%
-%
- /* Command-line options: */%
- OPTS opts;%
- opts.Vflg = FALSE; /* variable col width */%
- opts.Sflg = FALSE; /* stretch output columns to fit */%
- opts.Gutter = 1; /* gutter width */%
- opts.ColWidth = 0; /* fixed col width */%
- opts.Ncols = 0; /* number of cols */%
- opts.Width = 79; /* output width */%
- opts.Tabsize = 8; /* tab size */%
- opts.PageLen = 0; /* page length */%
- opts.ColSep[0] = '\0'; /* column separator string */%
- opts.Leader = '\0'; /* leader char for column separation */%
-%
- while ((c = getopt (argc, argv, "vsg:c:n:w:l:L:t:T:")) != EOF) {%
- switch (c) {%
- case 'v':%
- if (opts.ColWidth != 0) errflg++;%
- opts.Vflg = TRUE;%
- break;%
- case 's':%
- opts.Sflg = TRUE;%
- break;%
- case 'c':%
- if (opts.Vflg == TRUE) errflg++;%
- opts.ColWidth = atoi(optarg);%
- if (opts.ColWidth < 1) errflg++;%
- break;%
- case 'g':%
- opts.Gutter = atoi(optarg);%
- if (opts.Gutter < 0) errflg++;%
- break;%
- case 'n':%
- opts.Ncols = atoi(optarg);%
- if (opts.Ncols < 0) errflg++;%
- break;%
- case 'w':%
- opts.Width = atoi(optarg);%
- if (opts.Width < 1) errflg++;%
- break;%
- case 'l':%
- opts.PageLen = atoi(optarg);%
- if (opts.PageLen < 1) errflg++;%
- break;%
- case 'T':%
- opts.Tabsize = atoi(optarg);%
- if (opts.Tabsize < 1) errflg++;%
- break;%
- case 'L':%
- opts.Leader = optarg[0];%
- break;%
- case 't':%
- strcpy(opts.ColSep, optarg);%
- break;%
- case '?':%
- errflg++;%
- }%
- }%
- Opts = opts; /* copy to global, so we know what was */%
- /* actually user-specified and what we */%
- /* computed */%
- if (errflg) {%
- Usage();%
- exit (2);%
- }%
- if (optind >= argc)%
- totlines = ReadIn("-", &Lines); /* read stdin */%
- else {%
- for( ; optind < argc; optind++) {%
- totlines += ReadIn(argv[optind], &Lines); /* read text files */%
- }%
- }%
- if (totlines > 0)%
- Columnate(&Lines, &opts, totlines);%
-}%
-%
-Usage()%
-{%
- fprintf(stderr,"\n\%
-Usage: %s [-cglnstvwLT] <files>\n\%
- Use '-' for stdin.\n\%
- Options:\n\%
- -v variable-width columns (default: fixed-width)\n\%
- -s spread columns to fit output width (default: don't spread)\n\%
- -g # separate columns by a #-character 'gutter'.\n\%
- -c # column width (size) (default: max line length of input)\n\%
- -n # use # columns (default: program picks max # that will fit)\n\%
- -w # output width is # characters/line (default: 80)\n\%
- -l # page length is # lines (default: infinite)\n\%
- -L c leader character is 'c' (default: space)\n\%
- -t s use string \"s\" as separator (default: enough space to line up)\n\%
- -T # use #-space tabs (default: 8)\n");%
-}%
END.colm.c
if (test -d column.c) then
echo column.c is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f column.c) then
echo 'Should I overwrite the existing version of column.c (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f column.c) then
echo Overwriting column.c...
else
echo Creating column.c...
fi
sed 's/-//;s/%$//' << 'END.column.c' > column.c
-/*----------------------------------------------------------------------%
- * column.c - does the actual work of columnating the list of lines%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- *----------------------------------------------------------------------%
- */%
-%
-#include <stdio.h>%
-#include "std.h"%
-#include "colm.h"%
-%
-extern int debug;%
-%
-static char SCCSId[] = "@(#)column.c 1.1 6/3/88 (MASSCOMP) 22:44:43";%
-%
-/* Returns success or failure. */%
-BOOLEAN%
-Columnate(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines; /* total number of text lines to columnate */%
-{%
- /* First, check to make sure it's possible to columnate the output. */%
- if (findmax(list, totlines) > opts->Width) {%
- fprintf(stderr, "\%
-Error: Some input line is longer than the output width of %d chars.\n",%
- opts->Width);%
- exit(1);%
- }%
- if (!SinglePageCol(list, opts, totlines))%
- return MultiPageCol(list, opts, totlines);%
- else return TRUE;%
-}%
-%
-/* SinglePageCol returns TRUE or FALSE, according to whether the text */%
-/* will fit on the page. */%
-static BOOLEAN%
-SinglePageCol(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines;%
-{%
- int try_again = TRUE;%
- while (try_again) {%
- try_again = FALSE;%
- %
- if (opts->ColWidth > 0 && opts->Ncols > 0)%
- return FixedColumns(list, opts, totlines);%
- if (opts->Vflg == TRUE)%
- return VarColumns(list, opts, totlines);%
- if (opts->Ncols > 0 && opts->Sflg == TRUE && opts->ColWidth == 0) {%
- opts->ColWidth = opts->Width / opts->Ncols;%
- return FixedColumns(list, opts, totlines);%
- }%
- /* We can figure out the column width by finding the largest */%
- /* string. Once we find that, we process again to pick up any */%
- /* other options. */%
- if (opts->ColWidth == 0) {%
- opts->ColWidth = findmax(list, -1) + opts->Gutter;%
- try_again = TRUE;%
- }%
- /* If we know the column width and the output width, we can */%
- /* figure out the number of columns. */%
- if (opts->ColWidth > 0 && opts->Width > 0 && opts->Ncols == 0) {%
- opts->Ncols = opts->Width / opts->ColWidth;%
- try_again = TRUE;%
- }%
- }%
-}%
-%
-/* Same return value as for SinglePageCol. */%
-/* FixedColumns() requires that ColWidth, NCols and Width be set. */%
-BOOLEAN%
-static FixedColumns(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines;%
-{%
- NODE *cols[MAX_COLS]; /* NODE pointers for each column */%
- register int i,j;%
- int outlines; /* total # of output lines */%
-%
- /* This is the easy case - just put out the lines. */%
-%
- ASSERT(opts->ColWidth > 0 && opts->Ncols > 0);%
- /* We only print an error message here if the user actually */%
- /* specified (via capital-O Opts) a number of columns and width. */%
- if (Opts.Ncols > 0 && Opts.ColWidth > 0 &&%
- opts->ColWidth * opts->Ncols > opts->Width) {%
- fprintf(stderr,%
- "%d columns of %d characters won't fit in output width",%
- opts->Ncols, opts->ColWidth);%
- fprintf(stderr," of %d chars.\n", opts->Width);%
- exit(3);%
- }%
- /* It's not always possible to form up proper columns from a given */%
- /* number of input lines; 'proper' here means all columns even */%
- /* except the last, which can be as short as one element. For */%
- /* instance, five text lines can't be formed into four columns. */%
- /* But they can be formed into three columns of two each, except */%
- /* the last column which will contain only one line. */%
- /* Here we always opt for using fewer columns instead. */%
- /* We spread the extra space (if any) out over all the columns. */%
-%
- outlines = (totlines + opts->Ncols - 1) / opts->Ncols;%
-%
- if ((totlines + outlines-1) / outlines != opts->Ncols) {%
- int extraspace = opts->ColWidth%
- * (opts->Ncols - (totlines + outlines-1) / outlines);%
- /* Here again, we only print the error message if the user */%
- /* explicitly requested (via Opts) a number of columns. If we */%
- /* figured it out, we don't need to tell her that we guessed */%
- /* wrong. */%
- if (Opts.Ncols > 0) {%
- fprintf(stderr,"Can't form %d text lines into %d proper columns; ",%
- totlines, opts->Ncols);%
- fprintf(stderr,"using %d columns instead.\n",%
- (totlines + outlines-1) / outlines);%
- }%
- opts->Ncols = (totlines + outlines-1) / outlines;%
- /* Only spread columns if cwidth wasn't explicitly specified. */%
- if (Opts.ColWidth == 0 && opts->Sflg == TRUE)%
- opts->ColWidth += extraspace / opts->Ncols;%
- return FixedColumns(list, opts, totlines);%
- }%
- if (opts->PageLen > 0 && outlines > opts->PageLen) return FALSE;%
- for (i = 0; i < opts->Ncols; i++)%
- cols[i] = findn(list, i * outlines);%
-%
- for (j = 0; j < outlines; j++) {%
- for (i = 0; i < opts->Ncols; i++) {%
- if (cols[i] != list) {%
- Output(cols[i]->string, opts->ColWidth);%
- if (i != opts->Ncols - 1 && cols[i+1] != list)%
- ToCol(opts->ColWidth * (i+1), opts);%
- cols[i] = cols[i]->next;%
- }%
- }%
- OutNL();%
- }%
-}%
-%
-BOOLEAN%
-static MultiPageCol(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines;%
-{%
- fprintf(stderr,"Can't do multi-page columnation (yet).\n");%
- return FALSE;%
-}%
END.column.c
if (test -d lists.c) then
echo lists.c is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f lists.c) then
echo 'Should I overwrite the existing version of lists.c (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f lists.c) then
echo Overwriting lists.c...
else
echo Creating lists.c...
fi
sed 's/-//;s/%$//' << 'END.lists.c' > lists.c
-/*----------------------------------------------------------------------%
- * These functions append to and search a doubly-linked, non-circular%
- * list of text lines.%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- *----------------------------------------------------------------------%
- */%
-%
-#include <stdio.h>%
-#include "std.h"%
-#include "colm.h"%
-%
-extern int debug;%
-%
-static char SCCSId[] = "@(#)lists.c 1.1 6/3/88 (MASSCOMP) 22:44:45";%
-%
-/* Declare the empty line list: */%
-/* Note that this header node is NOT part of the list. */%
-NODE Lines = { &Lines, &Lines, 0, NULL };%
-%
-/* Append a new string to the list: */%
-append(str, list)%
-char *str;%
-NODE *list;%
-{%
- register NODE *new;%
-%
- ASSERT(str != NULL);%
- ASSERT(list != NULL);%
-%
- NEW(new, NODE, 1); /* get a node */%
- NEW(new->string, char, strlen(str) + 1); /* get string storage */%
-%
- strcpy(new->string, str); /* copy the string into the storage */%
- new->length = strlen(str); /* store the length, for speed */%
-%
- new->next = list; /* link it onto the end of the list. */%
- new->prev = list->prev;%
- new->prev->next = new;%
- list->prev = new;%
-}%
-%
-/* Linearly search the next 'n' items of the list for longest string */%
-/* If n is negative, the search goes forever. */%
-int%
-findmax(list, n)%
-NODE *list;%
-int n;%
-{%
- register NODE *current = list->next;%
- NODE *longest = current;%
-%
- ASSERT(list != NULL);%
- ASSERT(list->next != NULL);%
- ASSERT(list->prev != NULL);%
-%
- for ( ; current != list && n != 0; current = current->next) {%
- if (current->length > longest->length)%
- longest = current;%
- if (n > 0) n--;%
- }%
- ASSERT(longest != NULL);%
- return longest->length;%
-}%
-%
-/* Add up the lengths of all the strings in the list. */%
-/* If n > 0, look only at the next 'n' items. */%
-/* If n < 0, look through to the end. */%
-int%
-total_chars(list, n)%
-NODE *list;%
-int n;%
-{%
- register NODE *current;%
- int total = 0;%
-%
- ASSERT(list != NULL);%
- ASSERT(list->next != NULL);%
- ASSERT(list->prev != NULL);%
-%
- for (current = list->next; current != list && n != 0;%
- current = current->next) {%
- total += current->length;%
- if (n > 0) n--;%
- }%
- return total;%
-}%
-%
-NODE *%
-findn(list, n)%
-NODE *list;%
-int n;%
-{%
- register NODE *current = list->next;%
-%
- ASSERT(list != NULL);%
- ASSERT(list->next != NULL);%
- ASSERT(list->prev != NULL);%
-%
- for ( ; current != list && n != 0; current = current->next, n--)%
- ;%
- ASSERT(current != list);%
- return current;%
-}%
END.lists.c
if (test -d output.c) then
echo output.c is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f output.c) then
echo 'Should I overwrite the existing version of output.c (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f output.c) then
echo Overwriting output.c...
else
echo Creating output.c...
fi
sed 's/-//;s/%$//' << 'END.output.c' > output.c
-/*----------------------------------------------------------------------%
- * output - output routines for auto-columnator%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- *----------------------------------------------------------------------%
- */%
-%
-#include "stdio.h"%
-#include "std.h"%
-#include "colm.h"%
-%
-static char SCCSId[] = "@(#)output.c 1.1 6/3/88 (MASSCOMP) 22:44:46";%
-%
-static OutCol = 0; /* current output column */%
-%
-Output(s, maxlen)%
-char *s;%
-int maxlen;%
-{%
- OutCol += printf("%.*s", maxlen, s);%
-}%
-%
-/* This ignores the opts right now. */%
-ToCol(tocol, opts)%
-int tocol; /* column to move to (org 0) */%
-OPTS *opts; /* how to move there */%
-{%
- if (opts->ColSep[0] != '\0')%
- printf("%s", opts->ColSep);%
- if (opts->Leader == '\0') { /* no leader, use spaces & tabs */%
- while (OutCol < (tocol - tocol % opts->Tabsize)) {%
- putchar('\t');%
- OutCol += opts->Tabsize;%
- OutCol -= OutCol % opts->Tabsize;%
- }%
- }%
- while (OutCol < tocol) {%
- putchar(opts->Leader == '\0' ? ' ' : opts->Leader);%
- OutCol++;%
- }%
-}%
-%
-OutNL()%
-{%
- putchar('\n');%
- OutCol = 0;%
-}%
END.output.c
if (test -d readin.c) then
echo readin.c is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f readin.c) then
echo 'Should I overwrite the existing version of readin.c (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f readin.c) then
echo Overwriting readin.c...
else
echo Creating readin.c...
fi
sed 's/-//;s/%$//' << 'END.readin.c' > readin.c
-/*----------------------------------------------------------------------%
- * ReadIn - read a file into a list of lines.%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- *----------------------------------------------------------------------%
- */%
-%
-#include <stdio.h>%
-#include "std.h"%
-#include "colm.h"%
-%
-#define MAX_LEN 20000 /* maximum string length */%
-%
-extern int debug;%
-%
-static char SCCSId[] = "@(#)readin.c 1.1 6/3/88 (MASSCOMP) 22:44:47";%
-%
-ReadIn(fname, list)%
-char *fname;%
-NODE *list;%
-{%
- char Instr[MAX_LEN];%
- FILE *infile = NULL;%
- int TotalLines = 0; /* total # of lines read */%
-%
- if (!strcmp(fname, "-"))%
- infile = stdin;%
- else if ((infile = fopen(fname, "r")) == NULL) {%
- fprintf(stderr,"Can't open file %s\n.", fname);%
- exit(9);%
- }%
- while (fgets(Instr, MAX_LEN, infile)) {%
- if (*Instr == '\0') {%
- fprintf(stderr,%
- "Error: Null found in supposedly line-oriented data.\n");%
- exit(2);%
- }%
- TotalLines++;%
- Instr[strlen(Instr)-1] = '\0'; /* strip newline */%
- append(Instr, list); /* add it to the list */%
- ASSERT(list->prev != NULL);%
- }%
- return TotalLines;%
-}%
END.readin.c
if (test -d vcolumn.c) then
echo vcolumn.c is an existing directory. Cannot overwrite it.
exit 2
fi
if (test -f vcolumn.c) then
echo 'Should I overwrite the existing version of vcolumn.c (y/n)? \c'
read response
if (test $response != y) then exit 99
fi
fi
if (test -f vcolumn.c) then
echo Overwriting vcolumn.c...
else
echo Creating vcolumn.c...
fi
sed 's/-//;s/%$//' << 'END.vcolumn.c' > vcolumn.c
-/*----------------------------------------------------------------------%
- * vcolumn.c - columnates with variable-size columns%
- * Copyright c. 1988, Gary Oberbrunner.%
- * This program may be freely redistributed providing that this source code%
- * and the accompanying copyright notice are preserved intact.%
- *----------------------------------------------------------------------%
- */%
-%
-#include <stdio.h>%
-#include "std.h"%
-#include "colm.h"%
-%
-extern int debug;%
-void ClearWidths();%
-%
-static char SCCSId[] = "@(#)vcolumn.c 1.2 6/3/88 (MASSCOMP) 23:11:49";%
-%
-BOOLEAN%
- VarColumns(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines;%
-{%
- ASSERT(Opts.ColWidth == 0);%
- /* Only auto-columnate if she didn't say how many columns, or if */%
- /* the requested number of columns fails. */%
- if (Opts.Ncols == 0 || ManVarColumns(list, opts, totlines) == FALSE)%
- AutoVarColumns(list, opts, totlines);%
-}%
-%
-BOOLEAN%
- ManVarColumns(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines;%
-{%
- int outlines;%
- int widths[MAX_COLS]; /* column-width table */%
- register NODE *current;%
- register int line, col;%
- int twidth = 0;%
- %
- ASSERT(opts->Ncols > 0);%
- outlines = (totlines + opts->Ncols - 1) / opts->Ncols;%
- %
- ClearWidths(widths, MAX_COLS);%
- for (current = list->next, col = 0, line=0;%
- current != list && totlines != 0;%
- current = current->next, totlines--) {%
- if (current->length > widths[col])%
- widths[col] = current->length;%
- /* Do next line, and if at bottom start next column */%
- if (++line >= outlines) {%
- col++;%
- line = 0;%
- }%
- }%
- for (col = 0; col < opts->Ncols; col++)%
- if (col != opts->Ncols -1)%
- widths[col] += opts->Gutter;%
- twidth += widths[col];%
- if (twidth > opts->Width) {%
- fprintf(stderr,"\%
-%d text columns won't fit into output width of %d chars; %d chars too wide.\n",%
- opts->Ncols, opts->Width, twidth - opts->Width);%
- return FALSE;%
- }%
- OutVCols(list, opts, totlines, outlines, widths);%
- return TRUE;%
-}%
-%
-BOOLEAN%
- AutoVarColumns(list, opts, totlines)%
-NODE *list;%
-OPTS *opts;%
-int totlines;%
-{%
- int widths[MAX_COLS]; /* column-width table */%
- register int outlines;%
- int avglen;%
- %
- /* We start with the smallest possible number of output lines and */%
- /* successively increase by ones until it works. */%
- %
- /* First, compute the smallest possible outlines: */%
- outlines = max(1, total_chars(list, totlines) / opts->Width);%
- %
- while (1) {%
- ASSERT(outlines <= totlines); /* runaway check */%
- ClearWidths(widths, MAX_COLS);%
- if (VariCol(list, opts, totlines, outlines, widths) == TRUE)%
- break;%
- outlines++;%
- }%
- /* Now opts->Ncols is correct, and VariCol has filled in widths[]. */%
- OutVCols(list, opts, totlines, outlines, widths);%
- return TRUE;%
-}%
-static void%
- ClearWidths(w, nc)%
-int w[];%
-int nc;%
-{%
- ASSERT (nc > 0);%
- while (nc--)%
- w[nc] = 0;%
-}%
-%
-static BOOLEAN%
- VariCol(list, opts, textlines, outlines, widths)%
-NODE *list;%
-OPTS *opts;%
-int textlines;%
-int outlines;%
-int widths[];%
-{%
- register int col; /* current column */%
- register int line; /* current out line */%
- register int twidth = 0;%
- register NODE *current;%
- %
- for (current = list->next, col = 0, line=0;%
- current != list && textlines != 0;%
- current = current->next, textlines--) {%
- if (current->length > widths[col])%
- widths[col] = current->length;%
- /* Do next line, and if at bottom start next column */%
- if (++line >= outlines) {%
- col++;%
- line = 0;%
- }%
- }%
- if (line != 0) col++;%
- opts->Ncols = col;%
- for (col = 0; col < opts->Ncols; col++) {%
- if (col != opts->Ncols -1)%
- widths[col] += opts->Gutter;%
- twidth += widths[col];%
- }%
- if (twidth <= opts->Width) { /* we made it */%
- /* Partition the extra space as evenly as possible */%
- int extra_chars = opts->Width - twidth;%
- while (extra_chars > 0 && opts->Ncols > 1 && opts->Sflg == TRUE)%
- for (col = 0; col < opts->Ncols-1 && extra_chars > 0; col++) {%
- widths[col]++;%
- extra_chars--;%
- }%
- return (TRUE);%
- }%
- return FALSE;%
-}%
-%
-static OutVCols(list, opts, textlines, outlines, widths)%
-NODE *list;%
-OPTS *opts;%
-int textlines;%
-int outlines;%
-int widths[];%
-{%
- register int col, line;%
- int ccol; /* current character column position */%
- NODE *cols[MAX_COLS];%
- %
- /* Get pointers to text lines, one for each column */%
- for (col = 0; col < opts->Ncols; col++) {%
- cols[col] = findn(list, outlines * col);%
- }%
- for (line = 0; line < outlines; line++) {%
- ccol = 0;%
- for (col = 0; col < opts->Ncols; col++) {%
- if (cols[col] != list) {%
- Output(cols[col]->string, widths[col]);%
- if (col != opts->Ncols - 1 && cols[col+1] != list)%
- ToCol(ccol += widths[col], opts);%
- cols[col] = cols[col]->next;%
- }%
- }%
- OutNL();%
- }%
-}%
END.vcolumn.c
exit 0
#-------------------------------- end of archive; cut here -------------------
--
Remember, Truth is not beauty; (617)692-6200x2445
Information is not knowledge; Beauty is not love; Gary Oberbrunner
Knowledge is not wisdom; Love is not music; ...!masscomp!garyo
Wisdom is not truth; Music is the best. - FZ ....garyo@masscomp