troff / pic bar graph program

Dan Flak flak at mcgp1.UUCP
Thu Feb 14 10:34:36 AEST 1991


bar is a poor programmer's bar graph generator using pic and troff to
draw the pictures. It is a generalization of a program I wrote to do a
specific report, and isn't intended to be too sophisticated. Nonetheless,
it still bears a superficial resemblance to a "real" graphics package.
And, if you don't have a real graphics package, at least it's easy to use.

If you follow the example used in the man page, you should get a bar
graph that looks something like:


         90                95.0                100.0
          ...................|....................|
          ___________________|______________      |
   Line 1 |__________________|______________| 99.0|
                             |                    |
          ___________________|_                   |
   Line 2 |__________________|_| 95.4             |
                             |                    |
          ______             |                    |
   Line 3 |_____| 91.2       |                    |
                             |                    |
          ____________       |                    |
   Line 4 |___________| 93.8 |                    |
                             |                    |
   Line 5 | ND               |                    |


Compilation is simple cc -o bar bar.c (Any questions?)

#----cut here and unpack using sh-----
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 02/13/1991 23:19 UTC by flak at mcgp1
# Source directory /usr/users/flak/jack
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1805 -rw-r--r-- bar.el
#   4344 -rw-rw-rw- bar.c
#
# ============= bar.el ==============
if test -f 'bar.el' -a X"$1" != X"-c"; then
	echo 'x - skipping bar.el (File already exists)'
else
echo 'x - extracting bar.el (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bar.el' &&
.de )k
..
.TH bar l local
.SH NAME
bar \- create a bar graph
.SH SYNOPSIS
.B bar [-iltu] <datafile>
.SH DESCRIPTION
.I bar
crates a stream of troff 'pic' commands to the standard output to
produce a horizontal bar for every line in the data file. 
.SH OPTIONS
.TP
.B i
increment. This value determines how many vertical partitions there will
be on the graph. (E.G. "5" means place a vertical scale every 5 units).
Default is 10.
.TP
.B l
lower limit. The lower limit for the data to be plotted. Default is 0.
.TP
.B t
title. The title string for the graph.
.TP
.B u
upper limit. The upper limit for the data to be plotted. Default is
100.
.SH EXAMPLES
DATA FILE FORMAT:
The data file is an ascii file containing one "record" per line (maximum 
of 30 records). A
record consists of the name of the item being plotted (maximum of 20 
characters) and its value separated by a vertical bar \f(CW(|)\fR.
.sp
.nf
datafile
\f(CWLine 1| 99.0
Line 2| 95.4
Line 3| 91.2
Line 4| 93.8
Line 5| ND\fR
.fi
.sp
bar -l 90 -u 100 -i 5 -t "TEST TITLE" datafile
.sp
In the example above will produce the commands to draw a bar graph 
containing 5 horizontal bars. The bars will extend from 90 to 100 with
vertical scale marks at 90, 95, and 100. The title of the bar will be
"TEST TITLE", and it will be centered on the top of the page.
.SH DIAGNOSTICS
The program will issue a warning message if the upper or lower limits
are exceeded by any of the data values. The keyword "ND" will be
interpreted by the program to mean "NO DATA". Put in the "value"
position in a record, it will cause no bar to be printed, and the
letters "ND" displayed instead of a data value.
.SH AUTHOR
Dan Flak, McCaw Cellular Communications Inc., 201 Elliott Ave W, Suite 105, 
Seattle, Wa 98119, 206-286-4355 (usenet: nwnexus!mcgp1!flak)
.SH BUGS
SHAR_EOF
chmod 0644 bar.el ||
echo 'restore of bar.el failed'
Wc_c="`wc -c < 'bar.el'`"
test 1805 -eq "$Wc_c" ||
	echo 'bar.el: original size 1805, current size' "$Wc_c"
fi
# ============= bar.c ==============
if test -f 'bar.c' -a X"$1" != X"-c"; then
	echo 'x - skipping bar.c (File already exists)'
else
echo 'x - extracting bar.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'bar.c' &&
/*+
X * File: bar.c
X *
X * Description: Produce a bar graph using pic and troff.
X *
X * Audit Trail:
X *   Original Author and Date: Dan Flak - November 26, 1990
X *   Update to general case: Dan Flak - February 13, 1991
X *
-*/
#ifdef VERSION
static char *SCCS = "%Z% %M% %I% %G% %U%";
#endif
X
/* #includes */
#include <stdio.h>
X
/* #defines  */
#define SAY printf
#define QUOTE '\042'
#define BACKSLASH '\134'
X
/* external variables */
X
extern char *optarg;
extern int  optind;
extern int  opterr;
extern int  optopt;
/* referenced external functions */
float atof();
X
/* internal functions */
void strip();
X
/* global variables   */
X
struct record
X	{
X	char  market[21];
X	float f;
X	char  m[8];
X	} rec[30];
X
float lower = 0, upper = 100, lineat = 10;
char  title[80] = "";
int nrecs = 0;
X
FILE *fin, *flimit, *fopen();
X
X
/* static variables   */
X
X
/*<
X * Function: main
X *
X * Description: Parse the data and make a pic file
X *
X * Data Type: int
X *
X * Arguments: 
X *    argv[] - data file.
X *
X *    Flags
X *    -l    lower limit
X *    -u    upper limit
X *    -i    increment
X *    -t    title string
X *
X * Returns:
X *
X * Side Effects:
X *
X * Calls:
X *
X * PDL
X *
>*/
X
int
main (argc, argv)
int  argc;
char **argv;
{
int c;
int i, j, k, nfound;
float range, perinch;
char linebuf[1000];
X
while ((c = getopt (argc, argv, "i:l:u:t:")) != EOF)
X	{
X	switch (c)
X		{
X		case 'i':
X			lineat = atof (optarg);
X		break;
X		case 'l':
X			lower = atof (optarg);
X		break;
X		case 'u':
X			upper = atof (optarg);
X		break;
X		case 't':
X			sprintf (title, "%s", optarg);
X		break;
X		default:
X			;
X		break;
X		}
X	}
X
/*  Read data file */
if ((fin = fopen (argv[optind], "r")) == NULL)
X	{
X	fprintf (stderr, "%s: can't open %s\n", argv[0], argv[optind]);
X	exit (-1);
X	}
X
while (fgets (linebuf, 1000, fin) != NULL)
X	{
X	nfound = sscanf (linebuf, "%[^|]|%[^'\n']",
X		rec[nrecs].market, rec[nrecs].m);
X	if (nfound == 2)
X		{
X		strip (rec[nrecs].m);
X		if (strncmp (rec[nrecs].m, "ND", 2))
X			{
X			rec[nrecs].f = atof (rec[nrecs].m);
X			}
X		else
X			{
X			rec[nrecs].f = lower;
X			}
X		nrecs++;
X		}
X	}
X
fclose (fin);
X
/*  Check upper and lower bounds  */
X
for (i = 0; i < nrecs; i++)
X	{
X	if (rec[i].f < lower)
X		{
X		fprintf (stderr, "Warning: lower limit exceeded %s - %f\n", 
X			rec[i].market, rec[i].f);
X		}
X
X	if (rec[i].f > upper)
X		{
X		fprintf (stderr, "Warning: upper limit exceeded %s - %f\n",
X			rec[i].market, rec[i].f);
X		}
X	}
X
X
/*  Build the file that will plot the graph  */
X
printf (".de )k\n..\n");
printf (".PH\n");
printf (".ps 12\n");
printf (".vs 12\n");
printf (".ce 3\n");
printf ("%cs+4%cfB%s%cfP%cs0\n", 
X	BACKSLASH, BACKSLASH, title, BACKSLASH, BACKSLASH);
printf (".ps13\n");
printf (".br\n");
printf (".DS\n");
printf (".PS\n");
printf ("\n# set invisible refernece box\n");
printf ("boxht = 7.0; boxwid = 4.5\n");
printf ("move to (1.5, -4.0); OB: box invis %c %c\n", QUOTE, QUOTE);
printf ("\n# set standard box height for 12 point pitch\n");
printf ("boxht = .1667\n");
range = upper - lower;
perinch = 4.5 / range;
printf ("\n# workaround for bug in 'old' pic\n");
printf ("%c   %c at OB.nw + (0, .2)\n", '"', '"');
printf ("\n# add title reference lines\n");
printf ("%c%4.1f%c at OB.nw + (0, .2)\n", 
X	'"', lower, '"');
for (k = 0; k < range / lineat; k++)
X	{
X	printf ("%c%4.1f%c at OB.nw + (%f, .2)\n", 
X		'"', lower + (k + 1) * lineat, '"',
X		(k + 1) * lineat * perinch);
X	}
for (i = 0; i < nrecs; i++)
X	{
X	printf ("# Graph for %s \n", rec[i].market);
X	printf ("boxwid = %f\n", (rec[i].f - lower) * perinch);
X	printf ("%c%s%c at OB.nw + (-.1, -%f) rjust\n", 
X		'"', rec[i].market, '"', i * .3333);
X	printf ("move to OB.nw + (0, -%f); box\n", i * .3333);
X	printf ("%c%s%c at last box.e + (.1, 0) ljust\n", 
X		'"', rec[i].m, '"');
X	putchar ('\n');
X	}
printf ("\n# draw dashed reference lines\n");
for (k = 0; k < range / lineat; k++)
X	{
X	printf ("line from OB.nw + (%f, .1) to last box.sw + (%f, -.087) dashed\n",
X		(k + 1) * lineat * perinch, (k + 1) * lineat * perinch);
X	}
printf (".PE\n");
printf (".DE\n");
}
X
X
/*<
X * Function: strip (s)
X *
X * Description: Strip leading and trailing blanks from a string.
X *
X * Data Type: void
X *
X * Arguments: s - the string to be stripped.
X *
X * Returns: nothing!
X *
X * Side Effects:
X *
X * Calls:
X *
X * PDL
X *
>*/
X
void strip (s)
char *s;
{
char *ptr;
X
ptr = s;
while (*ptr++ == ' ')
sprintf (s, "%s", ptr);
return;
}
SHAR_EOF
chmod 0666 bar.c ||
echo 'restore of bar.c failed'
Wc_c="`wc -c < 'bar.c'`"
test 4344 -eq "$Wc_c" ||
	echo 'bar.c: original size 4344, current size' "$Wc_c"
fi
exit 0
-- 
       Dan Flak - McCaw Cellular Communications Inc., 201 Elliot Ave W.,
    Suite 105, Seattle, Wa 98119, 206-286-4355, (usenet: nwnexus!mcgp1!flak)



More information about the Alt.sources mailing list