rsalz@uunet.uu.net (Rich Salz) (09/19/89)
Submitted-by: hafro.is!gunnar (Gunnar Stefansson) Posting-number: Volume 20, Issue 5 Archive-name: reldb/part02 #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -d ./doc` then mkdir ./doc echo "mkdir ./doc" fi if `test ! -s ./doc/math.1` then echo "writting ./doc/math.1" cat > ./doc/math.1 << '\Rogue\Monster\' .\" Man page for math(1) .TH MATH 1 "1. April 1989" .SH NAME math - Simple mathematical summaries of a table .SH SYNOPSIS .B math [ .I < data ] .SH DESCRIPTION .B Math reads columnar data from the standard input and outputs a few summary statistics. .LP This is best explained by way of an example. Suppose the file .I data contains the lines: .nf x y z v - - - - 0 1 2 3 1 3 4 2 3 4 5 3 4 5 6 4 5 6 7 .fi where exactly one tab-character separates the columns (note that the second y-value is missing - denoted by two adjacent tabs). .LP The command .I math < data yields: .nf x y z v Type - - - - ---- 5 4 5 5 Freq 10 13 20 25 Sum 2 3 4 5 Mean 1.58114 1.70783 1.58114 1.58114 Stddev 4 5 6 7 Maximum 0 1 2 3 Minimum .fi on the standard output. .LP The output should be self-explanatory. .SH "SEE ALSO" .BR reldb(1),\ compute(1). .SH BUGS .LP .I Math assumes that two tabs in a row denotes a missing value. This is usually a correct assumption - an empty columns is normally a missing value and should not be counted or used in a sum. .LP .I Math only does simple checks for the number of digits appropriate for output. Sometimes this yields messy output, although most cases should be reasonable, as in the above example. .LP No checks for invalid data are made. \Rogue\Monster\ else echo "will not over write ./doc/math.1" fi if `test ! -s ./doc/testdb.1` then echo "writting ./doc/testdb.1" cat > ./doc/testdb.1 << '\Rogue\Monster\' .\" Man page for testdb(1) .TH TESTDB 1 "1. June 1989" .SH NAME testdb - test reldb programs .SH SYNOPSIS .B testdb .SH DESCRIPTION Testdb sets up a directory, testdb, as a subdirectory under the user's home directory and runs some of the .I reldb programs. .P See the output files for more information. .SH "SEE ALSO" .BR reldb(1),\ testgr(1). .SH BUGS Not all programs are tested. \Rogue\Monster\ else echo "will not over write ./doc/testdb.1" fi if `test ! -s ./doc/testgr.1` then echo "writting ./doc/testgr.1" cat > ./doc/testgr.1 << '\Rogue\Monster\' .\" Man page for testgr(1) .TH TESTGR 1 "1. June 1989" .SH NAME testgr - test plot programs in reldb package .SH SYNOPSIS .B testgr .SH DESCRIPTION Testdb sets up a directory, testgr, as a subdirectory under the user's home directory and copies sample programs and datafiles into it. .P See the shell scripts, t1, t2 etc. for more information. .SH "SEE ALSO" .BR reldb(1),\ testdb(1). .SH BUGS No known bugs. \Rogue\Monster\ else echo "will not over write ./doc/testgr.1" fi if `test ! -d ./misc` then mkdir ./misc echo "mkdir ./misc" fi if `test ! -s ./misc/install` then echo "writting ./misc/install" cat > ./misc/install << '\Rogue\Monster\' \Rogue\Monster\ else echo "will not over write ./misc/install" fi if `test ! -s ./misc/Makefile` then echo "writting ./misc/Makefile" cat > ./misc/Makefile << '\Rogue\Monster\' BINDIR=../bin CFLAGS= -DDEBUG=0 DESTFILES=$(BINDIR)/relprint $(BINDIR)/qscat all: @echo "Use make install to install the scripts" install: $(DESTFILES) touch install $(BINDIR)/relprint : relprint.sh cp relprint.sh $(BINDIR)/relprint chmod +x $(BINDIR)/relprint $(BINDIR)/qscat : qscat.sh cp qscat.sh $(BINDIR)/qscat chmod +x $(BINDIR)/qscat \Rogue\Monster\ else echo "will not over write ./misc/Makefile" fi if `test ! -s ./misc/relprint.sh` then echo "writting ./misc/relprint.sh" cat > ./misc/relprint.sh << '\Rogue\Monster\' #!/bin/sh # reldbprint -- prepares printing of reldb table using tbl. # # Usage: reldbprint title < reldb_table trap "rm -f /tmp/tmp$$" 2 15 caption="$*" # tablecaption cat - > /tmp/tmp$$ read head < /tmp/tmp$$ # first get the header line echo '.TS' # tell tbl this is a table echo 'center doublebox;' # and to draw a nice box around it set - $head captctrl=c # Tbl header for caption line1=c # Handle header for first column line3=l # assume first col is label shift for i # set up remaining tbl header lines of c's and n's do captctrl=$captctrl"s" line1=$line1"c" # Want to center column headers line3=$line3"n" # Assume rest of cols are numbers done line3=$line3"." # add the dot to end the tbl format echo $captctrl echo $line1 # output the tbl format echo $line3 # statements echo .sp .3c echo $caption # then the table caption echo .sp .3c echo = # double underline for caption echo .sp .1c echo "$head" # next line of table data is the prelude header echo .sp .1c echo "_" # underline the header in the table sed 1,2d < /tmp/tmp$$ # now for the body of the table=data file echo '.TE' # and end the pretty little thing rm -f /tmp/tmp$$ \Rogue\Monster\ else echo "will not over write ./misc/relprint.sh" fi if `test ! -s ./misc/qscat.sh` then echo "writting ./misc/qscat.sh" cat > ./misc/qscat.sh << '\Rogue\Monster\' #!/bin/sh # # qscat : a quick-and-dirty shell script for turning # Reldb files into files which can be run through grap(1) # to produce reasonable plots. # (I didn't say production-quality, but these are certainly a good # start - just edit the output) echo ' \!! rasterize=300 .DF .ce \fB'$*'\fR .G1 frame ht 2 wid 5 ' awk ' NR==1{for(i=1;i<=NF;i++){ name[i]=$(i) } print "label bot ","\"",name[1],"\"" } NR==3{for(i=1;i<=NF;i++){ prev[i]=$(i) if(i>1)print "\""name[i]"\" ljust at "$1","$(i) if(i==2)print "bullet at "$1","$(i) if(i==3)print "circle at "$1","$(i) if(i==4)print "plus at "$1","$(i) if(i==5)print "delta at "$1","$(i) if(i==6)print "box at "$1","$(i) if(i==7)print "star at "$1","$(i) if(i>=8)print "plus at "$1","$(i) } } NR>3{for(i=2;i<=NF;i++){ if(i==2){ print "line from "prev[1]","prev[i]" to "$1","$(i) print "bullet at "$1","$(i) } if(i==3){ print "line dashed from "prev[1]","prev[i]" to "$1","$(i) print "circle at "$1","$(i) } if(i==4){ print "line dotted from "prev[1]","prev[i]" to "$1","$(i) print "plus at "$1","$(i) } if(i==5){ print "delta at "$1","$(i) print "line dashed 0.1i from "prev[1]","prev[i]" to "$1","$(i) } if(i==6){ print "box at "$1","$(i) print "line from "prev[1]","prev[i]" to "$1","$(i) } if(i==7){ print "star at "$1","$(i) print "line from "prev[1]","prev[i]" to "$1","$(i) } if(i>=8){ print "plus at "$1","$(i) print "line from "prev[1]","prev[i]" to "$1","$(i) } prev[i]=$(i) } prev[1]=$1 }' echo '.G2 .DE' \Rogue\Monster\ else echo "will not over write ./misc/qscat.sh" fi if `test ! -d ./plot1.src` then mkdir ./plot1.src echo "mkdir ./plot1.src" fi if `test ! -s ./plot1.src/Makefile` then echo "writting ./plot1.src/Makefile" cat > ./plot1.src/Makefile << '\Rogue\Monster\' INCLUDES=/usr/local/include CFLAGS=-I$(INCLUDES) OBJ=plotfilter.o xplot.o hpglplot.o graplot.o BINDIR=../bin all: xplot hpglplot graplot plot.sh xplot : $(OBJ) cc $(XCCFLAGS) -o xplot plotfilter.o xplot.o -lXaw -lXt -lX11 -lm hpglplot : $(OBJ) cc -o hpglplot plotfilter.o hpglplot.o -lm graplot: graplot.o plotfilter.o cc -o graplot graplot.o plotfilter.o install: xplot graplot hpglplot plot.sh testgr.sh cp xplot graplot hpglplot $(BINDIR) cp plot.sh $(BINDIR)/plot chmod +x $(BINDIR)/plot cp testgr.sh $(BINDIR)/testgr chmod +x $(BINDIR)/testgr cp graplot $(BINDIR) touch install clean: rm -f $(OBJ) xplot hpglplot graplot \Rogue\Monster\ else echo "will not over write ./plot1.src/Makefile" fi if `test ! -s ./plot1.src/README` then echo "writting ./plot1.src/README" cat > ./plot1.src/README << '\Rogue\Monster\' This directory contains : xplot, a plot(1) filter for X11. hpglplot, a plot(1) filter for hpgl. graplot, a plot(1) filter for grap output. Xplot is derived from sunplot which arrived on the net a while ago. This program will open an X window for the plot output. After running make, try scat -E -Lw < data | xplot =300x300+100+100 It seems impossible to do some of the things required for simple plots, if using plot(5) only. Things like rotation and centering of labels are essential. Hence we have enhanced the commands a bit, and the enhancements are used by scat only if a special option is used. The enclosed plot-filters support these extensions. The hpgl-filter is a modified version of an hpgl-filter which arrived on the net. The modifications are simply to allow for rotation and centering. These modifications are the only reasons for reposting. Graplot will take plot(5)-data and write output for the grap-program. This is extremely handy for putting into a troff-style paper. I (gunnar@hafro) apologize for not having gotten formal permission from previous authors (notable Jim Constantine and Scott Sutherland) to publish this modification of their code. Their code was published on the net, however, and no E-mail addresses remained in the files when I obtained them. WARNING: There is a bug in xplot. For some strange reason, the window manager awm will crash when xplot is started without any coordinate options. This is easily solved by always using some coordinates, e.g. scat < data | plot -Tx =300x300+100+100 -- or as in the above example. If anyone finds the problem, please let me know. The problem does not seem to appear with uwm. \Rogue\Monster\ else echo "will not over write ./plot1.src/README" fi if `test ! -s ./plot1.src/hpglplot.c` then echo "writting ./plot1.src/hpglplot.c" cat > ./plot1.src/hpglplot.c << '\Rogue\Monster\' #include <sgtty.h> #include <stdio.h> #include <math.h> /* HP-GL plot(5) library */ /* - does NOT do line locking */ /* - aspect ratio is not maintained */ /* Jim Constantine */ /* Copyright 1985 Sun Microsystems Inc. */ /* Extensions by asta@hafro.is (March, 1989) */ /* Prepared for redistribution by gunnar@hafro.is */ /* Notable features, which are really bugs: This program assumes it is writing to a device. That causes problems when writing to e.g. hpgl2ps filters. Use of some special HPGL escape sequences may also cause problems */ openpl() { struct sgttyb sgarg; int local; ioctl( fileno(stdout), TIOCGETP, &sgarg); ioctl( fileno(stdout), TIOCLGET, &local); sgarg.sg_ispeed = sgarg.sg_ospeed = B9600; sgarg.sg_erase = sgarg.sg_kill = '#'; sgarg.sg_flags = EVENP | ODDP; local = LDECCTQ; ioctl( fileno(stdout), TIOCSETP, &sgarg); ioctl( fileno(stdout), TIOCLSET, &local); /*printf("IN;\033.P1:"); /* out - gs */ printf("IN;"); fflush(stdout); printf("PG;AP 3;CA 10;CC 20;SR 0.6,1.2;SP 1;\n"); fflush(stdout); } move(x, y) { printf("PU %d,%d;\n", x, y); } line(x1, y1, x2, y2) { printf("PU %d,%d PD %d,%d;\n", x1, y1, x2, y2); } label(s) char *s; { printf("LB%s\03;\n", s); } erase() { printf("PG;AF;\n"); /* feed page if paper has been writen on */ } point(x, y) { printf("PU %d,%d PD PU;\n", x, y); } cont(x, y) { printf("PD %d,%d;\n", x, y); } space(x1, y1, x2, y2) { printf("SC %d,%d %d,%d;\n", x1, x2, y1, y2); } arc(xc, yc, x1, y1, x2, y2) { /* args are: center, start, end */ float angle; angle = atan((float) (y2 - y1) / (float) (x2 - x1)) * 5.729578e+01; if ((x2 - x1) < 0) angle = 180.0 + angle; move(x2,y2); printf("AA %d,%d;%6.3f\n", x1, y1, angle); } circle(x, y, r) { move(x,y); printf("CI %d;\n",r); } linemod(s) /* line style */ char *s; { switch(s[3]) { case 't': /* dotTed */ printf("LT 1;\n"); break; case 'i': /* solId */ default: printf("LT ;\n"); break; case 'g': /* lonGdashed */ printf("LT 3;\n"); break; case 'r': /* shoRtdashed */ printf("LT 2;\n"); break; case 'd': /* dotDashed */ printf("LT 4;\n"); break; } } labelrotation(s) char *s; { switch(s[1]) { case 'h': /* horizontal */ printf("DI 1,0;\n"); break; case 'v': /* vertical */ printf("DI 0,1;\n"); break; } } labelplace(s) char *s; { switch(s[1]) { case 'u': /* center the label under the point */ printf("LO16;\n"); break; case 'o': /* center the label over the point */ printf("LO14;\n"); break; case 'l': /* center the label left at the point */ printf("LO18;\n"); break; case 'r': /* center the label right at the point */ printf("LO12;\n"); break; case 'c': /* center the label at the point */ printf("LO15;\n"); break; default: /* center the label at the point */ printf("LO15;\n"); break; } } selectcolor(s) char *s; { switch(s[1]) { case '1': /* select pen 1 */ printf("SP 1;\n"); break; case '2': /* select pen 2 */ printf("SP 2;\n"); break; case '3': /* select pen 3 */ printf("SP 3;\n"); break; case '4': /* select pen 4 */ printf("SP 4;\n"); break; case '5': /* select pen 5 */ printf("SP 5;\n"); break; case '6': /* select pen 6 */ printf("SP 6;\n"); break; case '7': /* select pen 7 */ printf("SP 7;\n"); break; case '8': /* select pen 8 */ printf("SP 8;\n"); break; default: /* select pen 1 */ printf("SP 1;\n"); break; } } closepl() { printf ("SP;NR;PG;\n"); } \Rogue\Monster\ else echo "will not over write ./plot1.src/hpglplot.c" fi if `test ! -s ./plot1.src/plotfilter.c` then echo "writting ./plot1.src/plotfilter.c" cat > ./plot1.src/plotfilter.c << '\Rogue\Monster\' #include <stdio.h> static char buf[256]; int argc_copy; char **argv_copy; main(argc, argv) int argc; char **argv; { int x1,y1,x2,y2,x3,y3; int r; char c; argc_copy = argc; argv_copy = argv; openpl(); while ((c = getc(stdin)) != EOF) { switch (c) { case 'm': /* move */ x1 = getint(); y1 = getint(); move(x1,y1); break; case 'n': /* cont */ x1 = getint(); y1 = getint(); cont(x1,y1); break; case 'p': /* point */ x1 = getint(); y1 = getint(); point(x1,y1); break; case 'l': /* line */ x1 = getint(); y1 = getint(); x2 = getint(); y2 = getint(); line(x1,y1,x2,y2); break; case 't': /* text */ string(buf); label(buf); break; case 'e': /* erase */ erase(); break; case 's': /* space */ x1 = getint(); y1 = getint(); x2 = getint(); y2 = getint(); space(x1,y1,x2,y2); break; case 'a': /* arc */ x1 = getint(); y1 = getint(); x2 = getint(); y2 = getint(); x3 = getint(); y3 = getint(); arc(x1,y1,x2,y3,x3,y3); break; case 'c': /* circle */ x1 = getint(); y1 = getint(); r = getint(); circle(x1,y1,r); break; case 'f': /* linemod */ string(buf); linemod(buf); break; case 'r': /* homemade labelrotation*/ string(buf); labelrotation(buf); break; case 'u': /* homemade labelplace*/ string(buf); labelplace(buf); break; case 'z': /* homemade colorfunction*/ string(buf); selectcolor(buf); break; default: fprintf(stderr, "%s: unknown command 0x%x", argv[0], c & 0xff); if (c >= ' ') fprintf(stderr, " '%c'\n", c); else fprintf(stderr, " '^%c'\n", c + '@'); } } closepl(); } getint() { /* get an integer stored in 2 ascii bytes. */ short b1, b2; if ((b1 = getchar()) == EOF) return (EOF); if ((b2 = getchar()) == EOF) return (EOF); b2 = b2 << 8; return (b2 | b1); } string(s) char *s; { for (; *s = getchar(); s++) { if (*s == '\n') break; } *s = '\0'; return; } \Rogue\Monster\ else echo "will not over write ./plot1.src/plotfilter.c" fi if `test ! -s ./plot1.src/xplot.c` then echo "writting ./plot1.src/xplot.c" cat > ./plot1.src/xplot.c << '\Rogue\Monster\' /************************************************************************ * Plot(5) interface library for XWindows * * * * Asta G. March 1989 * * Adapted from a code for suntools by: * * * * Scott Sutherland, November 1987 * * Boston University Math Department * * * * This was adapted from a code by: * * Jim Constantine, Janurary 1986 * * which was in turn based on work by: * * Mike Caplinger, Rice University, September 1984. * ***********************************************************************/ #include <stdio.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <strings.h> #define FONT "6x13.snf" #define ARG_FONT "font" /* plot stuff */ float xscale = 1.0, yscale = 1.0; float xorig = 0.0, yorig = 0.0; int x, y; int use_labelplace=0; /* 0=false, 1=true */ char *label_pl; int xheight, yheight, width; int winX, winY, winW, winH; /* xwindow stuff */ XWMHints xwmh = { (InputHint|StateHint), /* flags */ False, /* no input from keyboard */ NormalState, /* initial_state */ 0, /* icon pixmap */ 0, /* icon window */ 0, 0, /* icon location */ 0, /* icon mask */ 0, /* Window group */ }; char *ProgramName; void Usage () { fprintf (stderr, "usage: %s [-options ...]\n\n", ProgramName); fprintf (stderr, "where options include:\n"); fprintf (stderr, " -geometry geom size of window\n"); fprintf (stderr, "\n"); exit (1); } extern int argc_copy; extern char **argv_copy; char **ap; char *geom = NULL; Display *dpy; /* X server connection */ Screen *scr; Window win; /* Window ID */ GC gc; /* GC to draw with */ char *fontName; /* Name of the font to use */ XFontStruct *fontstruct; /* Font descriptor */ unsigned long fth, ftw, pad; /* Font size parameters */ unsigned long fg, bg, bd; /* Pixel values */ unsigned long bw; /* Border width */ XGCValues gcv; /* Struct for creating GC */ XEvent event; /* Event received */ XSizeHints xsh; /* Size hints for window manager */ char *geomSpec; /* Window geometry string */ XSetWindowAttributes xswa; /* Temporary Set Window Attribute struct Window win; /************************************************************************/ /* openpl */ /************************************************************************/ openpl() { /* Process arguments: */ ap = argv_copy; while (*++ap) { if (!strncmp(*ap, "-g", 2)) { if (*++ap) { geom = *ap; } else Usage (); } else if (**ap == '=') geom = *ap; } /* * Open the display using the $DISPLAY environment variable to locate * the X server. See Section 2.1. */ if ((dpy = XOpenDisplay(NULL)) == NULL) { fprintf(stderr, "%s: can't open %s\n", argv_copy[0], XDisplayName(NULL)); exit(1); } /* Select the font to use */ if ((fontName = XGetDefault(dpy, argv_copy[0], ARG_FONT)) == NULL) { fontName = FONT; } if ((fontstruct = XLoadQueryFont(dpy, fontName)) == NULL) { fprintf(stderr, "%s: display %s doesn't know font %s\n", argv_copy[0], DisplayString(dpy), fontName); exit(1); } fth = fontstruct->max_bounds.ascent + fontstruct->max_bounds.descent; /* fth = fontstruct->ascent + fontstruct->descent; */ ftw = fontstruct->max_bounds.width; /* * Select colors for the border, the window background, and the * foreground. */ bd = BlackPixel(dpy, DefaultScreen(dpy)); bg = WhitePixel(dpy, DefaultScreen(dpy)); fg = BlackPixel(dpy, DefaultScreen(dpy)); /* * Set the border width of the window */ bw = 3; /* * Create the Window with the information in the XSizeHints, the * border width, and the border & background pixels. See Section 3.3. */ scr = DefaultScreenOfDisplay(dpy); xsh.width = 500; xsh.height = 300; xsh.x = 0; xsh.y = 0; xsh.flags = (PPosition | PSize); if (geom) { XParseGeometry(geom, &xsh.x, &xsh.y, &xsh.width, &xsh.height); xsh.flags = (USPosition | USSize); } win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), xsh.x, xsh.y, xsh.width, xsh.height, bw, bd, bg); /* * Set the standard properties for the window managers. See Section * 9.1. */ XSetStandardProperties(dpy, win, "", "", None, argv_copy, argc_copy,&xsh); XSetWMHints(dpy, win, &xwmh); scr = DefaultScreenOfDisplay(dpy); /* * Ensure that the window's colormap field points to the default * colormap, so that the window manager knows the correct colormap to * use for the window. See Section 3.2.9. Also, set the window's Bit * Gravity to reduce Expose events. */ xswa.save_under=True; xswa.backing_store = Always; xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy)); xswa.bit_gravity = CenterGravity; XChangeWindowAttributes(dpy, win, (CWSaveUnder | CWBackingStore | CWColormap | CWBitGravity),&xswa); /* * Create the GC for plotting. See Section 5.3. */ gcv.font = fontstruct->fid; gcv.foreground = fg; gcv.background = bg; /* gcv.function=GXand; gcv.plane_mask=BlackPixel(dpy,DefaultScreen(dpy)) ^ WhitePixel(dpy,DefaultScreen(dpy)); */ gc = XCreateGC(dpy, win, (GCFont | GCForeground | GCBackground ), &gcv); /* * Specify the event types we're interested in - only Exposures. See * Sections 8.5 & 8.4.5.1 */ XSelectInput(dpy, win, ExposureMask); /* * Map the window to make it visible. See Section 3.5. */ XMapWindow(dpy, win); XNextEvent(dpy, &event); } /************************************************************************/ /* move */ /************************************************************************/ move(x1, y1) { x = scalex(x1); y = scaley(y1); } /************************************************************************/ /* cont */ /************************************************************************/ cont(x1, y1) { x1 = scalex(x1); y1 = scaley(y1); XDrawLine(dpy, win, gc, x, y, x1, y1); x = x1; y = y1; XFlush(dpy); } /************************************************************************/ /* point */ /************************************************************************/ point(x, y) { x = scalex(x); y = scaley(y); XDrawRectangle(dpy, win, gc, x, y, 1, 1); XFlush(dpy); } /************************************************************************/ /* line */ /************************************************************************/ line(x1, y1, x2, y2) { x1 = scalex(x1); y1 = scaley(y1); x2 = scalex(x2); y2 = scaley(y2); XDrawLine(dpy, win, gc, x1, y1, x2, y2); XFlush(dpy); } /************************************************************************/ /* circle */ /* Not implemented */ /************************************************************************/ circle(x1, y1, r) { x1=scalex(x1-r); y1=scaley(y1-r); width=scalex(2*r); XDrawArc(dpy,win,gc,x1,y1,width,width,0,23040); XFlush(dpy); } /************************************************************************/ /* arc */ /* Not implemented */ /************************************************************************/ arc(cx, cy, sx, sy, ex, ey) { } /************************************************************************/ /* label */ /************************************************************************/ label(s) char *s; { if(!use_labelplace){ XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); } else { switch(*label_pl){ case 'u': x=x-XTextWidth(fontstruct,s,strlen(s))/2; y=y+fth; XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); break; case 'o': /* center the label over the point */ x=x-XTextWidth(fontstruct,s,strlen(s))/2; XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); break; case 'l': /* center the label left at the point */ x=x-XTextWidth(fontstruct,s,strlen(s)); /* y=y-fth/2+fontstruct->ascent; */ y=y-fth/2+fontstruct->max_bounds.ascent; XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); break; case 'r': /* center the label right at the point */ /* y=y+fth/2; */ y=y-fth/2+fontstruct->max_bounds.ascent; XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); break; case 'c': /* center the label at the point */ x=x-XTextWidth(fontstruct,s,strlen(s))/2; y=y-fth/2+fontstruct->max_bounds.ascent; /* y=y+fth/2; */ XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); break; default: /* center the label at the point */ x=x-XTextWidth(fontstruct,s,strlen(s))/2; y=y-fth/2+fontstruct->max_bounds.ascent; /* y=y+fth/2; */ XDrawString(dpy, win, gc, x, y, s, strlen(s)); XFlush(dpy); break; } } } /************************************************************************/ /* labelplace -- a homemade function */ /************************************************************************/ labelplace(s) char *s; { switch(s[1]) { case 'u': /* center the label under the point */ use_labelplace=1; label_pl="u"; break; case 'o': /* center the label over the point */ use_labelplace=1; label_pl="o"; break; case 'l': /* center the label left at the point */ use_labelplace=1; label_pl="l"; break; case 'r': /* center the label right at the point */ use_labelplace=1; label_pl="r"; break; case 'c': /* center the label at the point */ use_labelplace=1; label_pl="c"; break; default: /* center the label at the point */ use_labelplace=1; label_pl="c"; break; } } /************************************************************************/ /* labelrotation - a homemade function */ /* not implemented */ /************************************************************************/ labelrotation(s) char *s; { switch(s[1]) { case 'h': /* horizontal */ break; case 'v': /* vertical */ break; } } /************************************************************************/ /* selectcolor - a homemade function */ /* not implemented */ /************************************************************************/ selectcolor(s) char *s; { switch(s[1]) { case '1': /* select pen 1 */ break; case '2': /* select pen 2 */ break; case '3': /* select pen 3 */ break; case '4': /* select pen 4 */ break; case '5': /* select pen 5 */ break; case '6': /* select pen 6 */ break; case '7': /* select pen 7 */ break; case '8': /* select pen 8 */ break; default: /* select pen 1 */ break; } } /************************************************************************/ /* erase */ /************************************************************************/ erase() { XClearWindow(dpy, win); XFlush(dpy); } /************************************************************************/ /* linemod */ /* Not implemented */ /************************************************************************/ linemod(s) char *s; { switch(s[3]) { case 't': /* dotTed */ break; case 'i': /* solId */ default: break; case 'g': /* lonGdashed */ break; case 'r': /* shoRtdashed */ break; case 'd': /* dotDashed */ break; } } /************************************************************************/ /* space */ /************************************************************************/ space(xorigi, yorigi, x1, y1) { xorig = xorigi; yorig = yorigi; xscale = ((float) xsh.width) / (x1 - xorig); yscale = ((float) xsh.height) / (y1 - yorig); } /************************************************************************/ /* closepl */ /************************************************************************/ closepl() { XFlush(dpy); sleep(100000); return; } /************************************************************************/ /* scalex */ /************************************************************************/ static scalex(xi) { float x; x = xi; x -= xorig; x = x * xscale; return((int) x); } /************************************************************************/ /* scaley */ /************************************************************************/ static scaley(yi) { float y; y = yi; y -= yorig; y = y * yscale; y = xsh.height - y; /* origin at lower left. */ return((int) y); } \Rogue\Monster\ else echo "will not over write ./plot1.src/xplot.c" fi if `test ! -s ./plot1.src/plot.sh` then echo "writting ./plot1.src/plot.sh" cat > ./plot1.src/plot.sh << '\Rogue\Monster\' #!/bin/sh # # plot -- plot filter; controls execution of filter for # appropriate device. # # DOES NOT CONTAIN AT&T CODE. # # There are currently available PD filters for at least HPGL, X11 # and Postscript. The first two are included in the reldb distribution, # as the xplot program is new and the hpglplot program has been extended # somewhat to accept a few extended plot(5)-commands. # # These three filters would seem to suffice for a very large number # of applications. Development of general utilities which use the # plot(5) output format would therefore seem to be of potentially # great use. # # case $1 in -T*) devarg=$1 shift ;; *) echo "Usage: plot -Tfilter [otherargs]" exit 1 ;; esac case $devarg in -Thpgl) hpglplot $* ;; -TX*|-Tx*) xplot $* ;; -Tps*) psplot $* ;; -Tgrap*) graplot $* ;; esac exit 0 \Rogue\Monster\ else echo "will not over write ./plot1.src/plot.sh" fi if `test ! -s ./plot1.src/graplot.c` then echo "writting ./plot1.src/graplot.c" cat > ./plot1.src/graplot.c << '\Rogue\Monster\' #include <sgtty.h> #include <stdio.h> #include <math.h> /* HP-GL plot(5) library */ /* - does NOT do line locking */ /* - aspect ratio is not maintained */ /* Jim Constantine */ /* Copyright 1985 Sun Microsystems Inc. */ /* Extensions by ingi@hafro.is (June, 1989) */ /* Prepared for redistribution by gunnar@hafro.is */ /* Notable features: This program is to be used to create troff files. It can be used to print to a device without putting the statements through a file. just use scat < file | graplot | lprenta8 */ static char stre[15]; static char just[10]; static char jus1[10]; static char tex1[10]; openpl() { struct sgttyb sgarg; int local; printf("\\!! rasterize=300\n"); printf(".G1\n"); printf("frame invis ht 4 wid 6.2\n"); printf("X=1\nY=0\n"); printf("draw solid\n"); } move(X, Y) { /* printf("move from X,Y to %d,%d\n",X,Y);*/ printf("X=%d\n",X); printf("Y=%d\n",Y); } line(X1, Y1, X2, Y2) { printf("line %s from %d,%d to %d,%d\n", stre,X1, Y1, X2, Y2); } label(s) char *s; { printf("\"%s\" %s at X%s,Y%s\n",s,tex1,just,jus1); } erase() { printf("\n"); /* feed page if paper has been writen on */ } point(X, Y) { printf("line %s from %d,%d to %d,%d\n",stre, X,Y,X, Y); } cont(X, Y) { printf("line %s from X,Y to %d,%d\n", stre,X, Y); printf("X=%d\n",X); printf("Y=%d\n",Y); } space(X1, Y1, X2, Y2) { printf("ticks bot out .0001i from %d to %d by %d \"\"\n",X1,X2,X2); printf("ticks left out .0001i from %d to %d by %d \"\"\n",X1,X2,X2); } arc(Xc, Yc, X1, Y1, X2, Y2) { /* args are: center, start, end */ } circle(X, Y, r) { } linemod(s) /* line stYle */ char *s; { switch(s[3]) { case 't': /* dotTed */ printf("new dotted\n"); strcpy(stre,"dotted"); break; case 'i': /* solId */ default: printf("new solid\n"); strcpy(stre,"solid"); break; case 'g': /* lonGdashed */ printf("new dashed\n"); strcpy(stre,"dashed"); break; case 'r': /* shoRtdashed */ printf("new dashed .5i\n"); strcpy(stre,"dashed .1i"); break; case 'd': /* dotDashed */ printf("new dashed .05i\n"); strcpy(stre,"dashed .05i"); break; } } labelrotation(s) char *s; { /* switch(s[1]) { case 'h': printf("DI 1,0\n"); case 'v': printf("DI 0,1\n"); } */} labelplace(s) char *s; { switch(s[1]) { case 'u': /* center the label under the point */ strcpy(just,"-0"); strcpy(jus1,"-0"); strcpy(tex1,"below"); break; case 'o': /* center the label over the point */ strcpy(just,"-0"); strcpy(jus1,"+0"); strcpy(tex1,"above"); break; case 'l': /* center the label left at the point */ strcpy(jus1,"-0"); strcpy(just,"-0"); strcpy(tex1,"rjust"); break; case 'r': /* center the label right at the point */ strcpy(jus1,"-0"); strcpy(just,"+0"); strcpy(tex1,"ljust"); break; case 'c': /* center the label at the point */ strcpy(just,"-0"); strcpy(jus1,"-0"); strcpy(tex1,""); break; default: /* center the label at the point */ strcpy(just,"-0"); strcpy(jus1,"-0"); strcpy(tex1,""); break; } } selectcolor(s) char *s; { /* switch(s[1]) { case '1': /* select pen 1 printf("SP 1\n"); break; case '2': /* select pen 2 printf("SP 2\n"); break; case '3': /* select pen 3 printf("SP 3\n"); break; case '4': /* select pen 4 printf("SP 4\n"); break; case '5': /* select pen 5 printf("SP 5\n"); break; case '6': /* select pen 6 printf("SP 6\n"); break; case '7': /* select pen 7 printf("SP 7\n"); break; case '8': /* select pen 8 printf("SP 8\n"); break; default: /* select pen 1 printf("SP 1\n"); break; } */ } closepl() { printf (".G2\n"); } \Rogue\Monster\ else echo "will not over write ./plot1.src/graplot.c" fi if `test ! -d ./plot1.src/Junk` then mkdir ./plot1.src/Junk echo "mkdir ./plot1.src/Junk" fi if `test ! -s ./plot1.src/Junk/graplot.c` then echo "writting ./plot1.src/Junk/graplot.c" cat > ./plot1.src/Junk/graplot.c << '\Rogue\Monster\' #include <sgtty.h> #include <stdio.h> #include <math.h> /* HP-GL plot(5) library */ /* - does NOT do line locking */ /* - aspect ratio is not maintained */ /* Jim Constantine */ /* Copyright 1985 Sun Microsystems Inc. */ /* Extensions by ingi@hafro.is (June, 1989) */ /* Prepared for redistribution by gunnar@hafro.is */ /* Notable features: This program is to be used to create troff files. It can be used to print to a device without putting the statements through a file. just use scat < file | graplot | lprenta8 */ static char stre[15]; static char just[10]; static char jus1[10]; static char tex1[10]; openpl() { struct sgttyb sgarg; int local; printf("\\!! rasterize=300\n"); printf(".G1\n"); printf("frame invis ht 4 wid 6.2\n"); printf("X=1\nY=0\n"); printf("draw solid\n"); } move(X, Y) { /* printf("move from X,Y to %d,%d\n",X,Y);*/ printf("X=%d\n",X); printf("Y=%d\n",Y); } line(X1, Y1, X2, Y2) { printf("line %s from %d,%d to %d,%d\n", stre,X1, Y1, X2, Y2); } label(s) char *s; { printf("\"%s\" %s at X%s,Y%s\n",s,tex1,just,jus1); } erase() { printf("\n"); /* feed page if paper has been writen on */ } point(X, Y) { printf("line %s from %d,%d to %d,%d\n",stre, X,Y,X, Y); } cont(X, Y) { printf("line %s from X,Y to %d,%d\n", stre,X, Y); printf("X=%d\n",X); printf("Y=%d\n",Y); } space(X1, Y1, X2, Y2) { printf("ticks bot out .0001i from %d to %d by %d \"\"\n",X1,X2,X2); printf("ticks left out .0001i from %d to %d by %d \"\"\n",X1,X2,X2); } arc(Xc, Yc, X1, Y1, X2, Y2) { /* args are: center, start, end */ } circle(X, Y, r) { } linemod(s) /* line stYle */ char *s; { switch(s[3]) { case 't': /* dotTed */ printf("new dotted\n"); strcpy(stre,"dotted"); break; case 'i': /* solId */ default: printf("new solid\n"); strcpy(stre,"solid"); break; case 'g': /* lonGdashed */ printf("new dashed\n"); strcpy(stre,"dashed"); break; case 'r': /* shoRtdashed */ printf("new dashed .5i\n"); strcpy(stre,"dashed .1i"); break; case 'd': /* dotDashed */ printf("new dashed .05i\n"); strcpy(stre,"dashed .05i"); break; } } labelrotation(s) char *s; { /* switch(s[1]) { case 'h': printf("DI 1,0\n"); case 'v': printf("DI 0,1\n"); } */} labelplace(s) char *s; { switch(s[1]) { case 'u': /* center the label under the point */ strcpy(just,"-0"); strcpy(jus1,"-15"); strcpy(tex1,""); break; case 'o': /* center the label over the point */ strcpy(just,"-0"); strcpy(jus1,"+15"); strcpy(tex1,""); break; case 'l': /* center the label left at the point */ strcpy(jus1,"-0"); strcpy(just,"-0"); strcpy(tex1,"rjust"); break; case 'r': /* center the label right at the point */ strcpy(jus1,"-0"); strcpy(just,"+0"); strcpy(tex1,"ljust"); break; case 'c': /* center the label at the point */ strcpy(just,"-0"); strcpy(jus1,"-0"); strcpy(tex1,""); break; default: /* center the label at the point */ strcpy(just,"-0"); strcpy(jus1,"-0"); strcpy(tex1,""); break; } } selectcolor(s) char *s; { /* switch(s[1]) { case '1': /* select pen 1 printf("SP 1\n"); break; case '2': /* select pen 2 printf("SP 2\n"); break; case '3': /* select pen 3 printf("SP 3\n"); break; case '4': /* select pen 4 printf("SP 4\n"); break; case '5': /* select pen 5 printf("SP 5\n"); break; case '6': /* select pen 6 printf("SP 6\n"); break; case '7': /* select pen 7 printf("SP 7\n"); break; case '8': /* select pen 8 printf("SP 8\n"); break; default: /* select pen 1 printf("SP 1\n"); break; } */ } closepl() { printf (".G2\n"); } \Rogue\Monster\ else echo "will not over write ./plot1.src/Junk/graplot.c" fi if `test ! -s ./plot1.src/testgr.sh` then echo "writting ./plot1.src/testgr.sh" cat > ./plot1.src/testgr.sh << '\Rogue\Monster\' #!/bin/sh # # testgr -- user script for testing reldb programs. # PLOTDIR=/usr/local/src/Reldb/testgr if [ ! -d $PLOTDIR ] then echo "I can't seem to find the test data and programs" echo "Please edit my PLOTDIR variable properly" echo "(It is now set to $PLOTDIR, which is incorrect)" exit 1 fi # Go home first - no need to clutter discs cd if [ ! -d testgr ] then mkdir testgr fi cd testgr PWD=`pwd` echo "Copying programs and data into $PWD - hold on ..." cp $PLOTDIR/* . echo "Now run the sample programs, for example 't1 | xplot =500x500+300+300'" \Rogue\Monster\ else echo "will not over write ./plot1.src/testgr.sh" fi if `test ! -s ./plot1.src/install` then echo "writting ./plot1.src/install" cat > ./plot1.src/install << '\Rogue\Monster\' \Rogue\Monster\ else echo "will not over write ./plot1.src/install" fi if `test ! -d ./reldb.src` then mkdir ./reldb.src echo "mkdir ./reldb.src" fi if `test ! -s ./reldb.src/addcol.sh` then echo "writting ./reldb.src/addcol.sh" cat > ./reldb.src/addcol.sh << '\Rogue\Monster\' #!/bin/sh # # addcol - add columns to a table # # Usage: addcol columns < data # # Author: gunnar@hafro.is # Revisions: none yet ? # # NOTE: This seems to generate an invalid table -- extra tabs # should be added in the data part. add= for i do add=$add' '$i done sed '1{ s/$/'"$add"'/ p s/[^ ]/-/g } 2d' \Rogue\Monster\ else echo "will not over write ./reldb.src/addcol.sh" fi if `test ! -s ./reldb.src/addup.c` then echo "writting ./reldb.src/addup.c" cat > ./reldb.src/addup.c << '\Rogue\Monster\' /* Procedure addup. Usage: addup p < data Typical input line : a(1) a(2) ... a(p) b(1) ... b(nb) Output : For each level of (a(1),...,a(p)), print the sum of all the b's. The a's are referred to as the 'by'-variables; The b's are the 'on'-variables. Revision history: Original author : gunnar@hafro.is (sometime in 86) All sorts of additions Mainly incorrect string manipulations also some dubious use of intermixed float and double - now all double. gunnar@hafro.is (April, 1989) General comments: This program is rarely used directly by a human. Rather, it is a piece of the subtotal program, - subtotal call first project to order the by-variables first and then pipes the output into addup. This is what's called quick-and-dirty programming, but it's a heck of a lot simpler than having to build project into subtotal. */ #include <stdio.h> #include <strings.h> #ifndef DEBUG #define DEBUG 0 /* Define positive for debug (can override in Makefile*/ #endif #define MAXV 25 /* maximum number of a-variables */ #define MAXLIN 150 /* maximum line length */ int debug=DEBUG; /* debug level*/ int p; /* numerical equiv. of arguments = number of by-vbls*/ int nonvar; /* number of on-variables */ int i; /* index */ double x[MAXV]; /* input b-vbls (i.e. one line at a time) */ main(argc,argv) int argc; char *argv[]; { char line[MAXLIN]; /* input line */ char oldline[MAXLIN]; /* previous input line */ int c; double sum[MAXV]; /* vector of sums for a b-val*/ /* read argument = # vbls into p */ if(debug) fprintf(stderr,"Into addup-routine\n"); if(argc==2 ){ if(sscanf(argv[1], "%d", &p) != 1) { printf("usage: addup p \n or: addup debuglevel p\n"); return(-1); } } else if (argc==3){ if(sscanf(argv[1], "%d", &debug) != 1) { printf("usage: addup p \n or: addup debuglevel p\n"); return(-1); } if(sscanf(argv[2], "%d", &p) != 1) { printf("usage: addup p \n or: addup debuglevel p\n"); return(-1); } } else { printf("usage: addup p \n or: addup debuglevel p\n"); return(-1); } if(debug>=2) fprintf(stderr,"Got argument:->%d<-\n",p); if(fgets(oldline,MAXLIN,stdin)==NULL){ fprintf(stderr,"Cannot read first line of input\n"); exit(1); } if(debug>=5) fprintf(stderr,"Got header:->%s<-\n",oldline); fputs(oldline,stdout); if(fgets(oldline,MAXLIN,stdin)==NULL){ fprintf(stderr,"Cannot read second line of input\n"); exit(1); } fputs(oldline,stdout); c=getline(oldline,p,x); nonvar=c; if(debug>=5){ fprintf(stderr,"Got first dataline(on-part):->%s<-\n",oldline); fprintf(stderr,"\tGot sum-variable:->%d<-\n",x[0]); fprintf(stderr,"\t# on vars:%d\n",nonvar); } addup(sum); while(c!=EOF){ c=getline(line,p,x); if(debug>=5){ fprintf(stderr,"Got dataline(on-part):->%s<-\n",line); fprintf(stderr,"\tGot sum-variable:->%lf<-\n",x[0]); fprintf(stderr,"\t# on vars:%d\n",c); } if( c!=EOF && strlen(oldline)==strlen(line) && !strcmp(oldline,line) ){ if(debug>=5){ fprintf(stderr,"Same by-columns-adding\n"); } addup(sum);/* same a-vbls;add */ }else{ if(debug>=5){ fprintf(stderr,"New by-cols-print old line(%s):\n",oldline); } output(oldline,sum); /* output */ if(debug>=5){ fprintf(stderr,"\told line>%s< becomes >%s<",oldline,line); } (void)strcpy(oldline,line); /* copy header */ if(c!=EOF) addup(sum);/* new and final a's*/ } } return(0); } getline(line,p,x) char line[MAXLIN]; /* remainder of input line (the b's=by-columns)*/ int p; /* no of vbls */ double x[MAXV]; /* columns to be summed */ { int i=0; int count=1; int c; char tmplin[MAXLIN]; if((c=getchar())==EOF) return(EOF); do { line[i++]=c; while((c=getchar())!='\t') /* get 'by' part as a string */ line[i++]=c; count++; }while(count<=p); line[i]='\0'; if(debug>=5)fprintf(stderr,"Input:by-vbls >%s<\n",line); count=0; do { i=0; c=getchar(); while(c!='\t'&&c!='\n'){ tmplin[i++]=c; c=getchar(); } tmplin[i]='\0'; if(debug>=5)fprintf(stderr,"\t next on-vbl >%s<\n",tmplin); if(i!=0){ sscanf(tmplin,"%lf",&x[count]); /* get 'on' variables */ if(debug>=5)fprintf(stderr,"\t on-vbl:%lf\n",x[count]); } else { if(debug>=5)fprintf(stderr,"\t empty on-vbl\n"); x[count]=0.; } count++; } while(c!='\n'); return(count); } /* getline */ addup(sum) double sum[MAXV]; /* vector of sums */ { static int first=1; if(debug>=2) fprintf(stderr,"Adding up:\n"); if(first){ if(debug>=5) fprintf(stderr,"\tinit\n"); for(i=0;i<nonvar;i++){ sum[i]=0.; /* initialize*/ first=0; } } for(i=0;i<nonvar;i++){ if(debug>=5) fprintf(stderr,"\tAdding %lf to %lf\n",x[i],sum[i]); sum[i]+=x[i]; /* sum for vbl i */ } } /* addup */ output(oldline,sum) char oldline[MAXLIN]; /* previous input line, a-values (on) */ double sum[MAXV]; /* vector of sums (b's-on vbls) for a fixed a-val*/ { for(i=0;i<MAXLIN&&oldline[i]!='\0'&oldline[i]!='\n';i++) printf("%c",oldline[i]); /* print text in beg. of line */ for(i=0;i<nonvar;i++){ /* cut down digits output */ if((double)(int)sum[i] == sum[i]) printf(" %ld",(long)sum[i]); else if((double)(int)sum[i]<sum[i]-.00001||sum[i]<1.) printf(" %lf",sum[i]); else printf(" %ld",(long)sum[i]); sum[i]=0; } printf("\n"); } \Rogue\Monster\ else echo "will not over write ./reldb.src/addup.c" fi if `test ! -s ./reldb.src/invert.sh` then echo "writting ./reldb.src/invert.sh" cat > ./reldb.src/invert.sh << '\Rogue\Monster\' #!/bin/sh # # invert -- inverse of matrix command. # awk 'NR==1{for(i=1;i<=NF;i++)name[i]=$(i)} NR==2{print name[1]" col data" ; print "---- --- ----"} NR>2{for(i=2;i<=NF;i++){OFS=" ";print $1,name[i],$(i)}}' \Rogue\Monster\ else echo "will not over write ./reldb.src/invert.sh" fi if `test ! -s ./reldb.src/bplokk.sh` then echo "writting ./reldb.src/bplokk.sh" cat > ./reldb.src/bplokk.sh << '\Rogue\Monster\' #!/bin/sh # # Simple jointable -- first file must be sufficiently short so that # a grep command can be set up from the whole file GREP=`awk ' BEGIN {printf("egrep ")} NR==3{FS=" ";printf("^%s",$1)} NR>3{FS=" ";printf("|^%s",$1)} END{print ""}' < $1 ` # uncomment the following if you want to see what is going on #echo $GREP head -2 < $2 $GREP < $2 \Rogue\Monster\ else echo "will not over write ./reldb.src/bplokk.sh" fi if `test ! -s ./reldb.src/check.sh` then echo "writting ./reldb.src/check.sh" cat > ./reldb.src/check.sh << '\Rogue\Monster\' #!/bin/sh # # check - checks sanity of reldb tables. # # The initial sed-command simply places dots in between two # adjacent tabs, to guarantee that they are regarded as two # fields by awk. for i do sed 's/ / . /g s/ / . /g' < $i |\ awk 'BEGIN {FS=" "} NR==1{ reclen=NF error=0} NR==2{ if(NF!=reclen){ print "Dashes do not match column heads" error=1 } } NR>2 { if(NF!=reclen){ print "Error in line number ",NR,"fields ",NF," headers ",reclen;error=1 } } END { if(error==0) print "Table '$i' is ok" }' done \Rogue\Monster\ else echo "will not over write ./reldb.src/check.sh" fi if `test ! -s ./reldb.src/compute.c` then echo "writting ./reldb.src/compute.c" cat > ./reldb.src/compute.c << '\Rogue\Monster\' /* compute.c -- implements the compute and select commands Pretty trivial program -- just reads the name-line and generates an awk-script saying 'name1=$1;name2=$2;...' and then the compute- or select-statement. Author: gunnar@hafro (way back then; probably 1987) 1989: I guess I shouldn't be writing to a string, but plead ignorance at the time... */ #include <stdio.h> #include <signal.h> #define MAXLINE 1000 char *skrarnafn="tmp......."; /* temporary file for awk-command */ main(argc,argv) int argc; char *argv[]; { char inpline[MAXLINE]; /* input line */ char *ptr; /* pointer into input line */ int select; /* =0 if compute, =1 if select */ int i=1; /* field number */ int die(); /* procedure to deal with exit */ FILE *fp,*fopen(),*popen(); signal(SIGINT,die); if(strcmp(argv[0],"select")) select=0; else select=1; sprintf(&skrarnafn[3],"%07d",getpid()); if((fp=fopen(skrarnafn,"w"))==NULL) errlog("Cannot open temporary file\n"); gets(inpline); puts(inpline); /* echo 1st header line */ fprintf(fp,"awk 'BEGIN {FS=\" \";OFS=\" \"}\n{"); ptr=inpline; do { while(*ptr!='\t'&&*ptr!='\0'&&*ptr!='\n') putc(*ptr++,fp); fprintf(fp,"=$(%d);",i); if(*ptr=='\t') *ptr++; i++; } while(*ptr!='\n'&&*ptr!='\0'); if(select) fprintf(fp,"if(%s)print ",argv[1]); /* select stmnt */ else fprintf(fp,"%s;print ",argv[1]); /* compute stmnt */ ptr=inpline; do { if(*ptr=='\t') putc(',',fp); else putc(*ptr,fp); ptr++; } while(*ptr!='\n'&&*ptr!='\0'); fprintf(fp,"}'\n"); fclose(fp); chmod(skrarnafn,0777); /* make file executable */ gets(inpline); puts(inpline); /* echo 2nd header line */ fflush(stdout); if((fp=popen(skrarnafn,"w"))==NULL) /* start up awk */ errlog("Cannot start up awk\n"); while(gets(inpline)!=NULL){ fputs(inpline,fp); fputc('\n',fp); } pclose(fp); wait(0); /* wait for awk to finish */ die(); } errlog(s) char *s; { fprintf(stderr,"%s",s); exit(1); } die(){ unlink(skrarnafn); exit(0); } \Rogue\Monster\ else echo "will not over write ./reldb.src/compute.c" fi if `test ! -s ./reldb.src/count.c` then echo "writting ./reldb.src/count.c" cat > ./reldb.src/count.c << '\Rogue\Monster\' /* Program to count the number of identical lines */ #include <stdio.h> #define MAXLIN 500 main(){ int count; /* counter for equal lines */ char line[MAXLIN],prev[MAXLIN]; /* current and previous lines */ fgets(line,MAXLIN,stdin); /* get 2 reldb header lines */ printf("count\t%s",line); /* and prepend count header */ fgets(line,MAXLIN,stdin); printf("-----\t%s",line); count=1; /* initialize counter */ fgets(prev,MAXLIN,stdin); while(fgets(line,MAXLIN,stdin)!=NULL){ if(strcmp(line,prev)){ /* 1 = not same as before */ printf("%d\t%s",count,prev); strcpy(prev,line); count=1; } else count++; } printf("%d\t%s",count,prev); } \Rogue\Monster\ else echo "will not over write ./reldb.src/count.c" fi if `test ! -s ./reldb.src/README` then echo "writting ./reldb.src/README" cat > ./reldb.src/README << '\Rogue\Monster\' This is reldb, a collection of programs to handle simple relational database operations. Shell scripts are stored with a .sh subscript, which is stripped off upon install. Edit the Makefile, in particular, set BINDIR to where you want the binaries and scripts to go. Typing 'make' will compile and install. Files: Makefile The Makefile (did you guess ?) README This file addcol.sh Script to add named columns to table addup.c Adds up some columns (part of subtotal). bplokk.sh Version of plokk for large numbers (even text). check.sh Checks sanity of named tables. columnlist.sh Lists names of columns in table. compute.c Computes new values into columns. count.c Counts repeated lines (c.f. uniq). dataplotpre.sh Reldb interface |Stat's dataplot. dbdict.sh Preliminary "data base dictionary" dbe.add.sh Add to database. dbe.change.sh Change table. invert.sh Inverse matrix command (invert). joinle.c Special join, good for length distributions. jointable.sh Reldb version of join. math.sh Compute simple statistics on table. matrix.c Go from (frequency,x,y) to matrix. mulregpre.sh Reldb interface to |Stat's regress program. number.sh Add a column with a linenumber (cf nl). pairpre.sh Reldb interface to |Stat's pair program. plokk.c Program to select lines according to list. preplot.sh Reldb interface to |Stat's dataplot. project.c Project columns out of a table. recode.c Recode a column according to list. regress.c Simple linear regression. rename.sh Rename columns. see.sh Display tabs etc. sideview.sh Display a table sideways. sorttable.sh Sort a table. subtotal.c Subtotal some columns. union.sh Append one table to another Someone please suggest a better name for this "package". The directory ../testdb contains some scripts to test the scripts and programs. Go there and type 'make', possibly after modifying BINDIR in the Makefile. \Rogue\Monster\ else echo "will not over write ./reldb.src/README" fi if `test ! -s ./reldb.src/dataplotpre.sh` then echo "writting ./reldb.src/dataplotpre.sh" cat > ./reldb.src/dataplotpre.sh << '\Rogue\Monster\' read x y read dum dataplot -n x$x -n y$y \Rogue\Monster\ else echo "will not over write ./reldb.src/dataplotpre.sh" fi if `test ! -s ./reldb.src/dbdict.sh` then echo "writting ./reldb.src/dbdict.sh" cat > ./reldb.src/dbdict.sh << '\Rogue\Monster\' awk 'BEGIN{FS=" "} NR==1{for(i=1;i<=NF;i++){ ind[i]=$(i) lengd[i]=length($(i)) } svidafj=NF; } NR>2{for(i=1;i<=NF;i++) if(length($(i))>lengd[i])lengd[i]=length($(i)); } END{ print "Atridi Lengd" print "------ -----" for(i=1;i<=svidafj;i++) print ind[i]" "lengd[i] }' \Rogue\Monster\ else echo "will not over write ./reldb.src/dbdict.sh" fi if `test ! -s ./reldb.src/dbe.add.sh` then echo "writting ./reldb.src/dbe.add.sh" cat > ./reldb.src/dbe.add.sh << '\Rogue\Monster\' : # # dbe.add # # Usage: dbe.add file # # Type ctrl-C to quit # # Method: # # First read the reldb header fro the file # # Then go into an everlasting loop, reading each field from the # terminal. After a record has been read, it is echo-ed to the end of the file. # read x < $1 while(true) do record="" tput clear for fld in $x do echo "$fld : \c" read temp record="$record $temp" done record=`echo "$record"|sed 's/^ //'` echo "$record" >> $1 done \Rogue\Monster\ else echo "will not over write ./reldb.src/dbe.add.sh" fi if `test ! -s ./reldb.src/dbe.change.sh` then echo "writting ./reldb.src/dbe.change.sh" cat > ./reldb.src/dbe.change.sh << '\Rogue\Monster\' #!/bin/sh # dbe.change # # Useage : dbe.add file # # Control-C is used to quit # # Method: # # First read the Prelude header from the file # # Loop over all records in the file. # Within each record, loop over all items in the record and # ask whether this item should be modified. # # Exactly one of the following should be set: # TERMINATOR='\c' INITIATOR='-n' # Also set one of the following: CLEAR=clear #CLEAR=tput clear trap "rm -f tempedit$$ tempoutput$$" 15 2 1 cp $1 tempedit$$ lines=`wc -l < $1` header=`sed '1{ s/ /_/g q }' < $1` ( read dumline echo "$dumline" > tempoutput$$ read dumline echo "$dumline" >> tempoutput$$ line=2 while [ $line -lt $lines ] do read inrec record="" $CLEAR for fld in $header do infield=`echo "$inrec" | sed 's/ .*//'` echo $INITIATOR "$fld (was $infield) : $TERMINATOR" read temp < /dev/tty if [ X"$temp" = X ] then record="$record $infield" else record="$record $temp" fi inrec=`echo "$inrec" | sed 's/^[^ ]* //'` done record=`echo "$record"|sed 's/^ //'` echo "$record" >> tempoutput$$ line=`expr $line + 1` done ) < tempedit$$ mv tempoutput$$ $1 rm -f tempedit$$ \Rogue\Monster\ else echo "will not over write ./reldb.src/dbe.change.sh" fi if `test ! -s ./reldb.src/joinle.c` then echo "writting ./reldb.src/joinle.c" cat > ./reldb.src/joinle.c << '\Rogue\Monster\' /* program to join many length distributions into one file. Just for fun, we compute these as a percentage distribution. Use: joinle files The only thing to watch out for is that lines may be missing in some files and the max/min-lengths will not be the same in all files. Those not concerned with marine research might not be so hot on length distributions -- let me know if you can transform this into something more generally useful. */ #include <stdio.h> #define MAXFILES 50 /* max # of files */ #define MAXLEN=350 /* max fish length*/ #define MAXLINE 1000 /* max length of input line */ int matrix[MAXLEN][MAXFILES]; /*Matrix of length distributions */ main(argc,argv) int argc; char **argv; { FILE *fp; FILE *fopen(); char **filelist=argv; char *curfile; int minlen=999999; int maxlen= -999999; int le,colnr; /* indices into file no & length */ int fj; int debug=0; /* -d gives debug */ char inpline[MAXLINE]; int totals[MAXFILES]; curfile= *++filelist; if(!strncmp(*filelist,"-d",2)){ debug=1; *filelist++; *argv++; argc--; } /* Now go through all the files */ for(colnr=1;colnr<argc;colnr++) { /* first verify that the next argument is a file */ curfile= *filelist; if(debug)fprintf(stderr,"Next file, %s", curfile); if(debug)fprintf(stderr,".a."); if((fp = fopen(*filelist++,"r"))==NULL){ fprintf(stderr,"Cannot open named file, %s\n",curfile); exit(1); } totals[colnr]=0; if(debug)fprintf(stderr,".b."); if(debug)fprintf(stderr,"Reading input file %s",curfile); if(debug)fprintf(stderr,".c."); fgets(inpline,MAXLINE,fp); /* skip header */ fgets(inpline,MAXLINE,fp); /* skip header */ if(debug)fprintf(stderr,".d."); while(fgets(inpline,MAXLINE,fp)!=NULL){ if(debug)fprintf(stderr,".e."); sscanf(inpline,"%d %d",&le,&fj); if(le<0 || le > MAXLEN){ fprintf(stderr,"Illegal length in file %s\n",*--filelist); fprintf(stderr,"Line is %s\n",inpline); exit(1); } if(le<minlen)minlen=le; if(le>maxlen)maxlen=le; matrix[le][colnr]=fj; totals[colnr]+=fj; } fclose(fp); if(debug)fprintf(stderr,"\n"); } printf("le"); for(colnr=1;colnr<argc;colnr++){ printf(" %s",*++argv); } printf("\n"); printf("--"); for(colnr=1;colnr<argc;colnr++){ printf(" --------"); } printf("\n"); for(le=minlen;le<=maxlen;le++){ printf("%d",le); for(colnr=1;colnr<argc;colnr++){ printf(" %.2lf",100.*(double)matrix[le][colnr]/ (double)totals[colnr]); } printf("\n"); } } \Rogue\Monster\ else echo "will not over write ./reldb.src/joinle.c" fi if `test ! -s ./reldb.src/jointable.sh` then echo "writting ./reldb.src/jointable.sh" cat > ./reldb.src/jointable.sh << '\Rogue\Monster\' trap "rm tmp$$ haus$$" 2 14 15 opt="" case $1 in '-n'|'-a1'|'-a2') opt=$1 shift ;; esac sed 1q < $1 | tr '\012' ' ' >haus$$ sed 's/^[^ ]* // 1q' < $2 >>haus$$ sed 'p s/[^ ]/-/g' < haus$$ sed '1,2d' < $2 >tmp$$ sed '1,2d' < $1 | join $opt -t" " - tmp$$ rm tmp$$ haus$$ \Rogue\Monster\ else echo "will not over write ./reldb.src/jointable.sh" fi if `test ! -s ./reldb.src/math.sh` then echo "writting ./reldb.src/math.sh" cat > ./reldb.src/math.sh << '\Rogue\Monster\' #!/bin/sh # # math -- compute some statistics on a table. # # BUG: <tab><tab> is used as a zero -- should be missing awk 'BEGIN {FS=" ";OFS=" "} NR==1 {print $0" Type";totf=NF} NR==2 {print $0" ----"; for(i=1;i<=NF;i++){ max[i]= -1e64; min[i]=1e64; }} NR>2 {for(i=1;i<=NF;i++){ if($(i)!=""){ sum[i]+=$(i); sum2[i]+=$(i)*$(i); freq[i]++; if($(i)>max[i]) max[i]=$(i); if($(i)<min[i]) min[i]=$(i); } }} END {for(i=1;i<=totf;i++) printf("%d\t",freq[i]); printf("Freq\n"); for(i=1;i<=totf;i++) if(sum[i]==int(sum[i])) printf("%d\t",sum[i]); else printf("%f\t",sum[i]); printf("Sum\n"); for(i=1;i<=totf;i++){ mean=sum[i]/freq[i] if(mean=int(mean)) printf("%d\t",sum[i]/freq[i]); else printf("%f\t",sum[i]/freq[i]); } printf("Mean\n"); for(i=1;i<=totf;i++){ stdev=sqrt((sum2[i]-sum[i]*sum[i]/freq[i])/(freq[i]-1)); if(stdev>1&&stdev<10) printf("%.5f\t",stdev); else printf("%f\t",stdev); } printf("Stddev\n"); for(i=1;i<=totf;i++) if(max[i]==int(max[i])) printf("%d\t",max[i]); else printf("%f\t",max[i]); printf("Maximum\n"); for(i=1;i<=totf;i++) if(min[i]==int(min[i])) printf("%d\t",min[i]); else printf("%f\t",min[i]); printf("Minimum\n"); } ' \Rogue\Monster\ else echo "will not over write ./reldb.src/math.sh" fi if `test ! -s ./reldb.src/matrix.c` then echo "writting ./reldb.src/matrix.c" cat > ./reldb.src/matrix.c << '\Rogue\Monster\' /* matrix: A program for setting up a simple frequency table, based on (count,x,y)-data */ #include <stdio.h> #define MAXX 250 #define MAXY 50 #define MINX 0 #define MINY 0 #define MAXLIN 500 #define MAXNAM 10 main(argc,argv) int argc; char *argv[]; { char line[MAXLIN],xname[MAXNAM],yname[MAXNAM],dum[MAXNAM]; char *format="\t%f"; /* Output table default format */ static float freq[MAXX][MAXY]; /* the frequencies */ float marg[MAXX]; /* marginal frequencies */ int x,y; /* input data : x,y, freq of x,y */ float n; int testmarg=1; /* =1=>skip empty lines =0=>print them*/ int minx,maxx,miny,maxy;/* computed bounds on input data */ while(--argc){ if(argv[1][0]=='-'){ if(argv[1][1]=='e') testmarg=0; /* print empty lines */ else{ fprintf(stderr,"Incorrect argument to matrix\n"); fprintf(stderr,"Usage : matrix [-e] [format]\n"); fprintf(stderr," -e : print empty lines\n"); fprintf(stderr," format : C printf format, default : %s\n",format); exit(1); } } else { format=argv[1]; } argv++; } fgets(line,MAXLIN,stdin); /* Reldb header line */ sscanf(line,"%s %s %s",dum,xname,yname);/* get names of columns */ fgets(line,MAXLIN,stdin); /* Reldb dash-line */ minx=MAXX;maxx=MINX;miny=MAXY;maxy=MINY; while(fgets(line,MAXLIN,stdin)!=NULL){ sscanf(line,"%f %d %d",&n,&x,&y); if(x>=MAXX||y>=MAXY){ fprintf(stderr,"Bound error : %s\n",line); continue; } ++x;++y; freq[x][y]+=n; marg[x]+=n; if(x>=maxx)maxx=x; if(y>=maxy)maxy=y; if(x<=minx)minx=x; if(y<=miny)miny=y; } printf("%s",xname); for(y=miny-1;y<maxy;){ printf("\t%s%d",yname,y++); } printf("\n--"); for(y=miny-1;y<maxy;y++){ printf("\t----"); } printf("\n"); for(x=minx;x<=maxx;x++){ if(marg[x]==0&&testmarg) continue; /* skip empties */ printf("%d",x-1); for(y=miny-1;y<maxy;){ printf(format,freq[x][++y]); } printf("\n"); } } /* main */ \Rogue\Monster\ else echo "will not over write ./reldb.src/matrix.c" fi if `test ! -s ./reldb.src/columnlist.sh` then echo "writting ./reldb.src/columnlist.sh" cat > ./reldb.src/columnlist.sh << '\Rogue\Monster\' #!/bin/sh # # columnlist.sh # # trivial sed-command to list column names of a table. # sed '1s/ /\ /g 1q' \Rogue\Monster\ else echo "will not over write ./reldb.src/columnlist.sh" fi if `test ! -s ./reldb.src/mulregpre.sh` then echo "writting ./reldb.src/mulregpre.sh" cat > ./reldb.src/mulregpre.sh << '\Rogue\Monster\' #!/bin/sh # # neat little script for interfacing with |Stat's "regress" read x read dummy /usr/stat/bin/regress -p $x \Rogue\Monster\ else echo "will not over write ./reldb.src/mulregpre.sh" fi if `test ! -s ./reldb.src/number.sh` then echo "writting ./reldb.src/number.sh" cat > ./reldb.src/number.sh << '\Rogue\Monster\' #!/bin/sh # # number -- add a number column awk ' NR == 1 {print "nr "$0} NR == 2 {print "-- "$0} NR > 2 {print NR-2" "$0}' < $1 \Rogue\Monster\ else echo "will not over write ./reldb.src/number.sh" fi if `test ! -s ./reldb.src/pairpre.sh` then echo "writting ./reldb.src/pairpre.sh" cat > ./reldb.src/pairpre.sh << '\Rogue\Monster\' : # Reldb version of unixstat's (|Stat) pair read x y read dum pair -p -x $y -y $y \Rogue\Monster\ else echo "will not over write ./reldb.src/pairpre.sh" fi if `test ! -s ./reldb.src/plokk.c` then echo "writting ./reldb.src/plokk.c" cat > ./reldb.src/plokk.c << '\Rogue\Monster\' /* Program to select lines according to values in the first column of each line. Usage : plokk fnam < file file = name of data file fnam = name of file containing values to be selected */ #include <stdio.h> main(argc,argv) int argc; char *argv[]; { char lina[1000]; /* input line*/ int n; /* first value in a data line */ int select[5000]; /* 1=values to select 0=skip*/ int nsel; /* running value to select */ FILE *fp,*fopen(); if((fp=fopen(argv[1],"r"))==NULL){ /* open selection file */ fprintf(stderr,"Usage : plokk selfil < datfil\n"); exit(-1); } nsel=0; /* initialize selection */ while(nsel<5000) select[nsel++]=0; fgets(lina,1000,fp); /* read selection file */ fgets(lina,1000,fp); while(fgets(lina,1000,fp)!=NULL){ sscanf(lina,"%d",&nsel); if(nsel< -1 || nsel> 5000){ fprintf(stderr,"plokk : index in selection file out of bounds %d\n",nsel); exit(1); } select[nsel+1]=1; } fclose(fp); fgets(lina,1000,stdin); printf("%s",lina); fgets(lina,1000,stdin); printf("%s",lina); while(fgets(lina,1000,stdin)!=NULL){ /* perform selection */ sscanf(lina,"%d",&n); if(n< -1 || n > 5000){ fprintf(stderr,"plokk : index in data file out of bounds %d\n",n); exit(1); } if(select[n+1]) printf("%s",lina); } } \Rogue\Monster\ else echo "will not over write ./reldb.src/plokk.c" fi if `test ! -s ./reldb.src/preplot.sh` then echo "writting ./reldb.src/preplot.sh" cat > ./reldb.src/preplot.sh << '\Rogue\Monster\' #!/bin/sh # # neat little script for interfacing with |Stat's dataplot. read x y read dum dataplot -n x$x -n y$y$ $* \Rogue\Monster\ else echo "will not over write ./reldb.src/preplot.sh" fi if `test ! -s ./reldb.src/project.c` then echo "writting ./reldb.src/project.c" cat > ./reldb.src/project.c << '\Rogue\Monster\' /* project: Author; johanna@hafro.is (1987?) */ #include <stdio.h> #define MAXLINE 4096 main(argc,argv) int argc; char *argv[]; { int i; int h; int a; char line[MAXLINE]; char tabv[1000][100]; int posv[1000]; i=0; argc--; header_lines(argc,argv); getline(line,MAXLINE,h,a); velja_dalka(tabv,line,&h,&a); gera_dalka(argc,argv,tabv,&h); cal_pos_val(argc,argv,tabv,posv); getline(line,MAXLINE,h,a); while((i = getline(line,MAXLINE,h,a)) > 0) { project_dalka(argc,posv,line); } exit(0); } header_lines(argc,argv) int argc; char *argv[]; { int i; int l; int s; int j; i=j=s=l=0; for(i=1;i <= argc;i++) { printf("%s",argv[i]); if(i==argc) printf("\n"); else printf("\t"); } for(j=1;j <= argc;j++) { l=strlen(argv[j]); for(s=1;s <= l;s++) printf("-"); if(j==argc) printf("\n"); else printf("\t"); } } velja_dalka(tabv,line,h,a) char tabv[1000][100]; char line[MAXLINE]; int *h; int *a; { int i; int j; *h=0; i=0; do { j=0; while((line[i] != '\t') && (line[i] != '\n')) { tabv[*h][j]=line[i]; j++; i++; } tabv[*h][j]='\0'; (*h)++; } while(line[++i] != '\0'); tabv[*h][0]='\0'; --h; (*a)=(*h); } gera_dalka(argc,argv,tabv,h) int argc; char *argv[]; char tabv[1000][100]; int *h; { int x; int y; char *strcpy(); x=y=0; for(x=1;x <= argc;x++) { y=0; while((tabv[y][0] != '\0') && (strcmp(argv[x],tabv[y]) != 0))y++; if (strcmp(argv[x],tabv[y]) == 0) { } else { strcpy(tabv[y],argv[x]); (*h)++; } } } cal_pos_val(argc,argv,tabv,posv) int argc; char *argv[]; char tabv[1000][100]; int posv[1000]; { int k; int l; for(k=1;k <= argc;k++) { l=0; while((strcmp(argv[k],tabv[l]) != 0) && (l < 1000))l++; l++; posv[k]=l; } } project_dalka(argc,posv,line) int argc; int posv[1000]; char line[MAXLINE]; { int d; int t; int l; for (d=1;d <= argc;d++) { l=0; for (t=1;t < posv[d];t++) { while ((line[l] != '\t') && (line[l] != '\0')) l++; l++; } while ((line[l] != '\t') && (line[l] != '\n')) putchar(line[l++]); if (d < argc) putchar('\t'); else putchar('\n'); } } getline(s,lim,h,a) char s[]; int lim; int h; int a; { int c; int i; int j; char *strcat(); j=0; c=0; i=0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++]=c; if (c == '\n') s[i++] = c; s[i] = '\0'; for(j=a;j < h;j++) { strcat(s,"\t"); } return(i); } \Rogue\Monster\ else echo "will not over write ./reldb.src/project.c" fi echo "Finished archive 2 of 3" exit -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.