Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!aplcen!uunet!abcfd20.larc.nasa.gov!amiga-request From: amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) Newsgroups: comp.sources.amiga Subject: v90i243: ListPlot - 2d plotting program, Part02/03 Message-ID: Date: 23 Aug 90 01:03:37 GMT Reply-To: Anthony M. Richardson Lines: 1868 Approved: tadguy@uunet.UU.NET (Tad Guy) X-Mail-Submissions-To: amiga@uunet.uu.net X-Post-Discussions-To: comp.sys.amiga Submitted-by: Anthony M. Richardson Posting-number: Volume 90, Issue 243 Archive-name: applications/listplot/part02 #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Csrc/ListPlot.c' <<'END_OF_FILE' X/* X * ListPlot.c X * X * Yet another plotting filter. X * X */ X#include X#include Xextern int errno; X#include X#include X#include X#include X#include "datatypes.h" X Xvoid ErrorExit(); Xchar *calloc(); X X/* initializations */ Xchar *Usage[] = { X "Usage: ListPlot [Options]\n", X 0 X}; Xchar *Function[] = { X "Function: Yet another plotting filter. For help, enter \"ListPlot help\".\n\tFor more verbose help, enter \"ListPlot Verbose=on help=all\".\n", X "\n", X "\tListPlot supports a number of different devices.\n", X "\n", X "\tListPlot reads from stdin and writes to stdout unless input and/or\n", X "\toutput files are specified on the command line.\n", X "\tThe program accepts a file of n-tuples. Each tuple consists of\n", X "\ta sequence of space separated numbers terminated with a newline.\n", X "\tThe first element of each tuple is assumed to be the independent\n", X "\tvariable. Each remaining element is plotted against the first to\n", X "\tproduce n-1 curves.\n", X "\n", X "\tListPlot takes a number of command line arguments that may be\n", X "\tused to control the appearance of the plots.\n", X "\tFor a list of the arguments enter:\n", X "\t\tListPlot Help=All.\n", X "\n", X "\t'Boolean' values accept values such as true, false,\n", X "\tyes, no, on, and off. (ex. PlotColor=yes)\n", X "\n", X "\t'String' values expect the strings to entered as\n", X "\tindicated and is case sensitive. (ex. Domain=All)\n", X "\n", X "\t'Dbl' values expect real numbers. (ex. AspectRatio=1.0)\n", X "\n", X "\t'Interval' values expect a pair of comma separated reals.\n", X "\t\t(ex. Range=-1.0,3.0)\n", X "\n", X "\t'Set' values expect a list of comma separated elements enclosed in\n", X "\tcurly braces ({}). (ex. LineStyle={MS,MMS,MSmmS})\n", X "\n", X "\tThe title and label variables accept strings that include\n", X "\tthe following control sequences:\n", X "\t\t#u: move up to superscript position (ended with #d)\n", X "\t\t#d: move down to subscript position (ended with #u)\n", X "\t\t#b: backspace to allow overprinting\n", X "\t\t##: the number symbol\n", X "\t\t#+: toggle overline mode\n", X "\t\t#-: toggle underline mode\n", X "\t\t#gx: Greek letter corresponding to Roman letter x\n", X "\n", X 0 X}; X Xbool GraphicsInProgress = FALSE; X X X/* argument definitions */ X/* GoldenRatio = (1+Sqrt(5))/2 */ X#define GOLDENRATIO 1.6180339887499 X#define ASPECTRATIO 1.0/GOLDENRATIO Xchar *H_AngularUnit[] = { X "\t'AngularUnit' specifies the angular unit of measure\n", X "\tused for polar plots. For angles in radians use\n", X "\t\tAngularUnit=radians\n", X (char *)NULL X}; XVALUE V_AngularUnit; XARGDEF A_AngularUnit = { X &V_AngularUnit, /* variable */ X "AngularUnit", /* ID */ X "degrees|radians", /* options */ X "string|string", /* format */ X "degrees", /* default */ X "string", /* Default type */ X H_AngularUnit X }; Xchar *H_AnnotationScale[] = { X "\t'AnnotationScale' controls the size of the characters\n", X "\tused to annotate the axises.\n", X (char *)NULL X}; XVALUE V_AnnotationScale; XARGDEF A_AnnotationScale = { X &V_AnnotationScale, /* variable */ X "AnnotationScale", /* ID */ X "dbl", /* options */ X "dbl", /* format */ X "0.50", /* default */ X "dbl", /* Default type */ X H_AnnotationScale X }; Xchar *H_AspectRatio[] = { X "\t'AspectRatio' controls the relative lengths of the vertical to\n", X "\thorizontal axes. The default is 1.0/GoldenRatio.\n", X "\t\tAspectRatio=0.618\n", X "\tIf set this value overrides the value of 'ViewPort'.\n", X (char *)NULL X}; XVALUE V_AspectRatio; XARGDEF A_AspectRatio = { X &V_AspectRatio, /* variable */ X "AspectRatio", /* ID */ X "dbl|Automatic", /* options */ X "dbl|string", /* format */ X "0.61803399", /* default */ X "dbl", /* Default type */ X H_AspectRatio X }; Xchar *H_Boxed[] = { X "\t'Boxed' adds axes to the edges of the plot.\n", X "\tIf 'Boxed is given a boolean value then axes are placed on\n", X "\tall of the edges. If 'Boxed' is given a string consisting\n", X "\tof one or more of 't','b','r','l' then axes are added to\n", X "\ttop, bottom, right and left edges respectively.\n", X (char *)NULL X}; XVALUE V_Boxed; XARGDEF A_Boxed = { X &V_Boxed, /* variable */ X "Boxed", /* ID */ X "boolean|*", /* options */ X "boolean|string", /* format */ X "yes", /* default */ X "boolean", /* Default type */ X H_Boxed X }; Xchar *H_Domain[] = { X "\t'Domain' may be used to specify the bounds on the X axis.\n", X (char *)NULL X}; XVALUE V_Domain; XARGDEF A_Domain = { X &V_Domain, /* variable */ X "Domain", /* ID */ X "interval|All|Automatic", /* options */ X "interval|string|string", /* format */ X "All", /* default */ X "string", /* Default type */ X H_Domain X }; Xchar *H_Gridding[] = { X "\t'Gridding' puts a grid on the plot.\n", X (char *)NULL X}; XVALUE V_Gridding; XARGDEF A_Gridding = { X &V_Gridding, /* variable */ X "Gridding", /* ID */ X "boolean", /* options */ X "boolean", /* format */ X "no", /* default */ X "boolean", /* Default type */ X H_Gridding X }; X X/* N.B. Help is treated differently than other variables and its X * arguments should only be of type "string"! X */ Xchar *H_Help[] = { X "\t'Help' provides some descriptive text for the user-settable\n", X "\tplotting variables. If the variable 'Verbose' is set then\n", X "\tan extended description is provided. To set verbose enter\n", X "\t\tListPlot Verbose=yes Help=[variable name | All].\n", X (char *)NULL X}; XVALUE V_Help; XARGDEF A_Help = { X &V_Help, /* variable */ X "Help", /* ID */ X "All|all|*", /* options */ X "string|string|string", /* format */ X "All", /* default */ X "string", /* Default type */ X H_Help X }; Xchar *H_LabelScale[] = { X "\t'LabelScale' specifies the relative size of the vertical and\n", X "\thorizontal axis labels. The typical range is [0.5 - 2.0].\n", X (char *)NULL X}; XVALUE V_LabelScale; XARGDEF A_LabelScale = { X &V_LabelScale, /* variable */ X "LabelScale", /* ID */ X "dbl", /* options */ X "dbl", /* format */ X "0.85", /* default*/ X "dbl", /* Default type */ X H_LabelScale X }; Xchar *H_LineColor[] = { X "\t'LineColor' may be used to specify a list of line colors for\n", X "\tplots with multiple curves if this feature is supported for\n", X "\ta particular output device.\n", X (char *)NULL X}; XVALUE V_LineColor; XARGDEF A_LineColor = { X &V_LineColor, /* variable */ X "LineColor", /* ID */ X "set", /* options */ X "set", /* format */ X "{Black,Red,Green,Blue,Yellow}", /* default*/ X "set", /* Default type */ X H_LineColor X }; Xchar *H_LineStyle[] = { X "\t'LineStyle' may be used to specify a list of line styles for\n", X "\tplots with multiple curves. Each linestyle is specified as\n", X "\ta sequence of pen down... pen up elements. The elements are encoded\n", X "\tusing the following characters to indicate element lengths:\n", X "\t\t'm':\t250 micron mark\n", X "\t\t'M':\t4 m's or a 1mm mark\n", X "\t\t's':\t250 micron space\n", X "\t\t'S':\t4 s's or a 1mm space\n", X "\n", X "\tFor example, a set of line styles might be indicated\n", X "\t\tLineStyle={MS,MMSS,MMSmmS,mmS,mmSmmSMMS}\n", X (char *)NULL X}; XVALUE V_LineStyle; XARGDEF A_LineStyle = { X &V_LineStyle, /* variable */ X "LineStyle", /* ID */ X "set", /* options */ X "set", /* format */ X "{MS,MMSS,MMSmmS,mmS,mmSmmSMMS}",/*default*/ X "set", /* Default type */ X H_LineStyle X }; Xchar *H_Origin[] = { X "\tThe 'Origin' option is not yet implemented. It is intended\n", X "\tthat this feature beused to specify the origin of the plot.\n", X (char *)NULL X}; XVALUE V_Origin; XARGDEF A_Origin = { X &V_Origin, /* variable */ X "Origin", /* ID */ X "interval|Automatic|Median", /* options */ X "interval|string|string", /* format */ X "Automatic", /* default */ X "string", /* Default type */ X H_Origin X }; Xchar *H_PlotColor[] = { X "\t'PlotColor' if TRUE causes the plot to generated in color if this\n", X "\tfeature is supported on a particular output device.\n", X (char *)NULL X}; XVALUE V_PlotColor; XARGDEF A_PlotColor = { X &V_PlotColor, /* variable */ X "PlotColor", /* ID */ X "boolean", /* options */ X "boolean", /* format */ X "no", /* default */ X "boolean", /* Default type */ X H_PlotColor X }; Xchar *H_PlotDevice[] = { X "\t'PlotDevice' specifies output device type.\n", X (char *)NULL X}; XVALUE V_PlotDevice; XARGDEF A_PlotDevice = { X &V_PlotDevice, /* variable */ X "PlotDevice", /* ID */ X "amiga|printer|iff|hp|aegis|postscript",/* options */ X "string|string|string|string|string|string",/* format */ X "amiga", /* default */ X "string", /* Default type */ X H_PlotDevice X }; Xchar *H_PlotJoined[] = { X "\t'PlotJoined' is set connects each data point with a line in the\n", X "\tcurrent line style. (ex PlotJoined=on )\n", X (char *)NULL X}; XVALUE V_PlotJoined; XARGDEF A_PlotJoined = { X &V_PlotJoined, /* variable */ X "PlotJoined", /* ID */ X "boolean", /* options */ X "boolean", /* format */ X "yes", /* default */ X "boolean", /* Default type */ X H_PlotJoined X }; Xchar *H_PlotPoints[] = { X "\t'PlotPoints' if set causes symbols to be plotted in the current\n", X "\tsymbol style at each data point. (ex. PlotPoints=true )\n", X (char *)NULL X}; XVALUE V_PlotPoints; XARGDEF A_PlotPoints = { X &V_PlotPoints, /* variable */ X "PlotPoints", /* ID */ X "boolean", /* options */ X "boolean", /* format */ X "false", /* default */ X "boolean", /* Default type */ X H_PlotPoints X }; Xchar *H_PlotTitle[] = { X "\t'PlotTitle' takes the plot title as an argument.\n", X "\tGreek symbols may be specified by preceding a character by\n", X "\t'#g'. Superscripts and subscripts may be specified using\n", X "\t'#u', '#d' respectively.\n", X (char *)NULL X}; XVALUE V_PlotTitle; XARGDEF A_PlotTitle = { X &V_PlotTitle, /* variable */ X "PlotTitle", /* ID */ X "*", /* options */ X "string", /* format */ X "", /* default */ X "string", /* Default type */ X H_PlotTitle X }; Xchar *H_PlotType[] = { X "\t'PlotType' specifies the 'graph paper' upon which the plot is drawn.\n", X "\tThe current implementation plots in\n", X "\t\tlinear-linear,\n", X "\t\tlog-linear,\n", X "\t\tlinear-log,\n", X "\t\tlog-log, and\n", X "\t\tpolar\n", X "\tformats.\n", X "\tFor the log type plots, the log of the data is computed\n", X "\tby ListPlot.\n", X "\tFor polar plots, see also 'AngularUnit' and 'PolarVariable'.\n", X (char *)NULL X}; XVALUE V_PlotType; XARGDEF A_PlotType = { X &V_PlotType, /* variable */ X "PlotType", /* ID */ X "linlin|loglin|linlog|loglog|polar",/* options */ X "string|string|string|string|string",/* format */ X "linlin", /* default */ X "string", /* Default type */ X H_PlotType X }; Xchar *H_PointScale[] = { X "\t'PointScale' controls the relative size of the data point symbols\n", X "\twhen data point symbols are being plotted.\n", X (char *)NULL X}; XVALUE V_PointScale; XARGDEF A_PointScale = { X &V_PointScale, /* variable */ X "PointScale", /* ID */ X "dbl", /* options */ X "dbl", /* format */ X "1.0", /* default */ X "dbl", /* Default type */ X H_PointScale X }; Xchar *H_PointSymbol[] = { X "\t'PointSymbol' specifies a list of symbols to be used when plotting\n", X "\tdata points. The symbols types are encoded as integers.\n", X "\tSee the PLPLOT library documentation to find the symbols\n", X "\tavailable.\n", X (char *)NULL X}; XVALUE V_PointSymbol; XARGDEF A_PointSymbol = { X &V_PointSymbol, /* variable */ X "PointSymbol", /* ID */ X "Automatic|set", /* options */ X "string|set", /* format */ X "Automatic", /* default */ X "string", /* Default type */ X H_PointSymbol X }; Xchar *H_PolarVariable[] = { X "\t'PolarVariable' for polar plots is used to specify\n", X "\twhether the independent variable is angular or radial.\n", X (char *)NULL X}; XVALUE V_PolarVariable; XARGDEF A_PolarVariable = { X &V_PolarVariable, /* variable */ X "PolarVariable", /* ID */ X "angle|radius", /* options */ X "string|string", /* format */ X "angle", /* default */ X "string", /* Default type */ X H_PolarVariable X }; Xchar *H_Orientation[] = { X "\t'Orientation' controls whether the plot is displayed in\n", X "\tlandscape or portrait orientation.\n", X (char *)NULL X}; XVALUE V_Orientation; XARGDEF A_Orientation = { X &V_Orientation, /* variable */ X "Orientation", /* ID */ X "portrait|landscape", /* options */ X "string|string", /* format */ X "landscape", /* default */ X "string", /* Default type */ X H_Orientation X }; Xchar *H_Range[] = { X "\t'Range' specifies the y axis bounds. (ex. Range=-1,1 )\n", X (char *)NULL X}; XVALUE V_Range; XARGDEF A_Range = { X &V_Range, /* variable */ X "Range", /* ID */ X "interval|All|Automatic", /* options */ X "interval|string|string", /* format */ X "All", /* default */ X "string", /* Default type */ X H_Range X }; Xchar *H_SubPages[] = { X "\t'SubPages' specifies the number of plots on a pages.\n", X "\tThis is a vestige of PLPLOT and I am not sure this has any use\n", X "\twithin the context of 'ListPlot. It might be useful for\n", X "\tcontrolling the size of the plots but the 'ViewPort' might be\n", X "\ta more direct solution.\n", X (char *)NULL X}; XVALUE V_SubPages; XARGDEF A_SubPages = { X &V_SubPages, /* variable */ X "SubPages", /* ID */ X "interval", /* options */ X "interval", /* format */ X "1.0,1.0", /* default */ X "interval", /* Default type */ X H_SubPages X }; Xchar *H_SupplyAbscissa[] = { X "\t'SupplyAbscissa' if set causes ListPlot to supply a value for\n", X "\tthe independent variable.\n", X (char *)NULL X}; XVALUE V_SupplyAbscissa; XARGDEF A_SupplyAbscissa = { X &V_SupplyAbscissa, /* variable */ X "SupplyAbscissa", /* ID */ X "boolean", /* options */ X "boolean", /* format */ X "no", /* default */ X "boolean", /* Default type */ X H_SupplyAbscissa X }; Xchar *H_TitleScale[] = { X "\t'TitleScale' controls the relative size of the title text.\n", X (char *)NULL X}; XVALUE V_TitleScale; XARGDEF A_TitleScale = { X &V_TitleScale, /* variable */ X "TitleScale", /* ID */ X "dbl", /* options */ X "dbl", /* format */ X "1.0", /* default */ X "dbl", /* Default type */ X H_TitleScale X }; Xchar *H_UseInputFile[] = { X "\t'UseInputFile' permits the specification of an input file if\n", X "\tyou would rather not use stdin.\n", X (char *)NULL X}; XVALUE V_UseInputFile; XARGDEF A_UseInputFile = { X &V_UseInputFile, /* variable */ X "UseInputFile", /* ID */ X "*", /* options */ X "string", /* format */ X "", /* default */ X "string", /* Default type */ X H_UseInputFile X }; Xchar *H_UseOutputFile[] = { X "\t'UseOutputFile' permits the specification of an output file if\n", X "\tyou would rather not use stdout.\n", X (char *)NULL X}; XVALUE V_UseOutputFile; XARGDEF A_UseOutputFile = { X &V_UseOutputFile, /* variable */ X "UseOutputFile", /* ID */ X "*", /* options */ X "string", /* format */ X "", /* default */ X "string", /* Default type */ X H_UseOutputFile X }; X/* Not used. V_AspectRatio may be used to control viewport in a nicer way */ Xchar *H_Verbose[] = { X "\t'Verbose' if set causes extended messaging.\n", X (char *)NULL X}; XVALUE V_Verbose; XARGDEF A_Verbose = { X &V_Verbose, /* variable */ X "Verbose", /* ID */ X "boolean", /* options */ X "boolean", /* format */ X "off", /* default */ X "boolean", /* Default type */ X H_Verbose X }; Xchar *H_ViewPort[] = { X "\t'ViewPort' allows control over the size of a plot. Takes\n", X "\ta viewing rectangle diagonal as an argument.\n", X "\t\t(ex. ViewPort=\\{0.1,0.3, 0.9,0.6\\} )\n", X (char *)NULL X}; XVALUE V_ViewPort; XARGDEF A_ViewPort = { X &V_ViewPort, /* variable */ X "ViewPort", /* ID */ X "rect", /* options */ X "rect", /* format */ X "{0.1,0.1,0.9,0.9}", /* default */ X "rect", /* Default type */ X H_ViewPort X }; Xchar *H_XLabel[] = { X "\t'XLabel' specifies X axis label. Greek characters may be included\n", X "\tby preceding the character with '#g'. Superscripts and subscripts\n", X "\tmay be included using '#u' and '#d' control sequences respectively.\n", X (char *)NULL X}; XVALUE V_XLabel; XARGDEF A_XLabel = { X &V_XLabel, /* variable */ X "XLabel", /* ID */ X "*", /* options */ X "string", /* format */ X "", /* default */ X "string", /* Default type */ X H_XLabel X }; Xchar *H_XTick[] = { X "\t'XTick' controls the spacing of major axis ticks and the number\n", X "\tof minor subdivisions. (ex. XTick=0.1,10 indicates major ticks at\n", X "\tunits of 0.1 with 10 minor subdivisions.)\n", X (char *)NULL X}; XVALUE V_XTick; XARGDEF A_XTick = { X &V_XTick, /* variable */ X "XTick", /* ID */ X "Automatic|interval", /* options */ X "string|interval", /* format */ X "Automatic", /* default */ X "string", /* Default type */ X H_XTick X }; Xchar *H_YLabel[] = { X "\t'YLabel' specifies Y axis label. Greek characters may be included\n", X "\tby preceding the character with '#g'. Superscripts and subscripts\n", X "\tmay be included using '#u' and '#d' control sequences respectively.\n", X (char *)NULL X}; XVALUE V_YLabel; XARGDEF A_YLabel = { X &V_YLabel, /* variable */ X "YLabel", /* ID */ X "*", /* options */ X "string", /* format */ X "", /* default */ X "string", /* Default type */ X H_YLabel X }; Xchar *H_YTick[] = { X "\t'YTick' controls the spacing of major axis ticks and the number\n", X "\tof minor subdivisions. (ex. YTick=0.1,10 indicates major ticks at\n", X "\tunits of 0.1 with 10 minor subdivisions.)\n", X (char *)NULL X}; XVALUE V_YTick; XARGDEF A_YTick = { X &V_YTick, /* variable */ X "YTick", /* ID */ X "Automatic|interval", /* options */ X "string|interval", /* format */ X "Automatic", /* default */ X "string", /* Default type */ X H_YTick X }; X XARGDEF *SymbolTable[] = { X &A_AngularUnit, X &A_AnnotationScale, X &A_AspectRatio, X &A_Boxed, X &A_Domain, X &A_Gridding, X &A_Help, X &A_LabelScale, X &A_LineColor, X &A_LineStyle, X &A_Orientation, X &A_Origin, X &A_PlotColor, X &A_PlotJoined, X &A_PlotPoints, X &A_PointScale, X &A_PointSymbol, X &A_PlotTitle, X &A_PlotDevice, X &A_PlotType, X &A_PolarVariable, X &A_Range, X &A_SubPages, X &A_SupplyAbscissa, X &A_TitleScale, X &A_UseInputFile, X &A_UseOutputFile, X &A_Verbose, X &A_ViewPort, X &A_XLabel, X &A_YLabel, X &A_XTick, X &A_YTick, X (ARGDEF *)NULL X }; X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X register int i; X int NTuples, TupleSize; X FLOAT **Data; X FILE *Fp; X void InterruptHandler(); X#ifdef ANSI_C X FLOAT **GetData(FILE *, int *, int *); X void ListPlot(FLOAT **,int ,int ); X#else X FLOAT **GetData(); X void ListPlot(); X#endif X X X get_args(argc, argv, SymbolTable, Usage, Function); X X if (VtoBoolean(V_Verbose)) { X fprintf(stderr, "Arg values:\n"); X for (i=0; SymbolTable[i]; i++) { X fputc('\t' ,stderr); X PrintArg(stderr, SymbolTable[i]); X } X } X X X if (signal(SIGINT, SIG_IGN) != SIG_IGN) X signal(SIGINT, InterruptHandler); X X X if (strlen(V_UseInputFile.val_u.udt_string) > 0) { X if ((Fp = fopen(V_UseInputFile.val_u.udt_string, "r")) == (FILE *)NULL) { X perror(V_UseInputFile.val_u.udt_string); X exit(errno); X } X } else { X Fp = stdin; X } X if (strlen(V_UseOutputFile.val_u.udt_string) > 0) { X if (!freopen(V_UseOutputFile.val_u.udt_string, "w", stdout)) { X perror(V_UseOutputFile.val_u.udt_string); X exit(errno); X } X } X if ((Data = GetData(Fp, &NTuples, &TupleSize)) == (FLOAT **)NULL) { X /* error */ X fprintf(stderr, "Unable to read data...\n"); X ErrorExit(); X } X X ListPlot(Data, NTuples, TupleSize); X} X X Xvoid XInterruptHandler() X{ X ErrorExit(); /* will not return */ X return; /* To satisfy some compilers */ X} X X Xvoid XErrorExit() X{ X if (GraphicsInProgress) X plend(); X exit(0); X} END_OF_FILE if test 19564 -ne `wc -c <'Csrc/ListPlot.c'`; then echo shar: \"'Csrc/ListPlot.c'\" unpacked with wrong size! fi chmod +x 'Csrc/ListPlot.c' # end of 'Csrc/ListPlot.c' fi if test -f 'Csrc/get_args.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Csrc/get_args.c'\" else echo shar: Extracting \"'Csrc/get_args.c'\" \(14827 characters\) sed "s/^X//" >'Csrc/get_args.c' <<'END_OF_FILE' X/* X * get_args.c X * X * command line argument parser X */ X#include X#include Xextern int errno; X#include X#include X#include X#include "datatypes.h" X X/* X#define min(A,B) AB? A : B X*/ X Xvoid Xget_args(argc, argv, Symbols, Usage, Function) Xint argc; Xchar **argv; XARGDEF *Symbols[]; Xchar *Usage[], *Function[]; X{ X register int i; X bool helped; X bool Help(), ParseHelp(); X X /* set default values */ X SetDefaults(Symbols); X X helped = FALSE; X for (i=1; iad_value, X Symbols[i]->ad_default, X Symbols[i]->ad_defaultType X ) != TRUE) { X /* error */ X fprintf(stderr,"Internal error: (SetDefaults) Unable to set "); X PrintArgDef(stderr,Symbols[i]); X errno = EINVAL; X exit(errno); X } X return; X} X X Xbool XSetValue(Val, ValStr, ValType) XVALUE *Val; Xchar *ValStr; Xchar *ValType; X{ X register int WidType; X X WidType = strlen(ValType); X if (strncmp(ValType, "string", WidType) == 0) { X return(SetString(Val, ValStr)); X } else if (strncmp(ValType, "dbl", WidType) == 0) { X return(SetDbl(Val, ValStr)); X } else if (strncmp(ValType, "float", WidType) == 0) { X return(SetFloat(Val, ValStr)); X } else if (strncmp(ValType, "int", WidType) == 0) { X return(SetInt(Val, ValStr)); X } else if (strncmp(ValType, "boolean", WidType) == 0) { X return(SetBool(Val, ValStr)); X } else if (strncmp(ValType, "byte", WidType) == 0) { X return(SetByte(Val, ValStr)); X } else if (strncmp(ValType, "interval", WidType) == 0) { X return(SetInterval(Val, ValStr)); X } else if (strncmp(ValType, "set", min(WidType,3)) == 0) { X return(SetSet(Val, ValStr, ValType, WidType)); X } else if (strncmp(ValType, "rect", WidType) == 0) { X return(SetRect(Val, ValStr)); X } else { X return(FALSE); X } X} X X Xbool XSetString(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X Val->val_type = string; X Val->val_u.udt_string = StrDup(ValStr); X return(TRUE); X} X X Xbool XSetDbl(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X double D; X X if (sscanf(ValStr, "%lf", &D) == 1) { X Val->val_type = dbl; X Val->val_u.udt_dbl = D; X return(TRUE); X } else { X return(FALSE); X } X} X X Xbool XSetFloat(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X float F; X X if (sscanf(ValStr, "%f", &F) == 1) { X Val->val_type = flt; X Val->val_u.udt_flt = F; X return(TRUE); X } else { X return(FALSE); X } X} X X Xbool XSetInt(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X int I; X X if (sscanf(ValStr, "%d", &I) == 1) { X Val->val_type = integer; X Val->val_u.udt_int = I; X return(TRUE); X } else { X return(FALSE); X } X} X X Xbool XSetBool(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X register int i, n; X char s[32]; X X n = min(strlen(ValStr),sizeof(s)-1); X for (i=0; ival_type = boolean; X Val->val_u.udt_bool = TRUE; X return(TRUE); X } else if ( X strncmp(s, "false", n) == 0 || X strncmp(s, "off", n) == 0 || X strncmp(s, "no", n) == 0 || X strncmp(s, "0", n) == 0) X { X Val->val_type = boolean; X Val->val_u.udt_bool = FALSE; X return(TRUE); X } else { X return(FALSE); X } X} X X Xbool XSetByte(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X char C; X Val->val_type = byte; X if (sscanf(ValStr, "%c", &C) == 1) { X Val->val_u.udt_byte = (char)C; X return(TRUE); X } else { X return(FALSE); X } X} X X Xbool XSetInterval(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X double lo, hi; X Val->val_type = interval; X if (sscanf(ValStr, "%lf,%lf", &lo,&hi) == 2) { X Val->val_u.udt_interval.int_lo = lo; X Val->val_u.udt_interval.int_hi = hi; X return(TRUE); X } else { X return(FALSE); X } X} X X Xbool XSetSet(Val, ValStr, ValType, WidType) XVALUE *Val; Xchar *ValStr; Xchar *ValType; Xint WidType; X{ X int i; X SET *S; X char *LeftBrace, *RightBrace; X char *Start; X char *sp; X bool Escape; X int WidStr; X char s[128]; X char *SkipBlanks(char *); X X Val->val_type = set; X S = &Val->val_u.udt_set; X S->list_n = 0; X S->list_head = (LATOM *)NULL; X S->list_tail = (LATOM *)NULL; X X if ((LeftBrace = strchr(ValStr, '{')) == (char *)NULL) { X /*error*/ X fprintf(stderr,"(SetSet) Invalid set specification: \"%s\" (missing left brace).\n", ValStr); X exit(0); X } X Start = LeftBrace+1; X if ((RightBrace = strchr(ValStr, '}')) == (char *)NULL) { X /*error*/ X fprintf(stderr,"(SetSet) Invalid set specification: \"%s\" (missing right brace).\n", ValStr); X exit(0); X } X WidStr = RightBrace - Start; X X for (sp=Start; *sp && *sp != '}'; ) { X/* sp = SkipBlanks(sp); */ X for ( Escape=FALSE,i=0; *sp && (Escape==TRUE || (Escape==FALSE && *sp != ',' && *sp != '}')); sp++) { X if (Escape == TRUE) { X s[i++] = *sp; X Escape = !Escape; X } else if (*sp == '\\' && Escape == FALSE) { X Escape = !Escape; X } else { X assert(*sp != '\\' && Escape == FALSE); X s[i++] = *sp; X } X } X s[i] = (char)NULL; X Append(S, (generic *)StrDup(s)); X if (*sp == ',') X ++sp; X } X X return(TRUE); X} X X Xbool XSetRect(Val, ValStr) XVALUE *Val; Xchar *ValStr; X{ X register char *sp; X register int i; X FLOAT *R; X char *LeftBrace, *RightBrace; X char *Start; X char s[128]; X char *SkipBlanks(char *); X double atof(); X X Val->val_type = rect; X R = Val->val_u.udt_rect.r_diag; X X if ((LeftBrace = strchr(ValStr, '{')) == (char *)NULL) { X /*error*/ X fprintf(stderr,"(SetRect) Invalid rect specification: \"%s\" (missing left brace).\n", ValStr); X exit(0); X } X Start = LeftBrace+1; X if ((RightBrace = strchr(ValStr, '}')) == (char *)NULL) { X /*error*/ X fprintf(stderr,"(SetRect) Invalid rect specification: \"%s\" (missing right brace).\n", ValStr); X exit(0); X } X X for (sp=Start; *sp && *sp != '}'; ) { X sp = SkipBlanks(sp); X for ( i=0; *sp && *sp != ',' && *sp != '}'; sp++) { X s[i++] = *sp; X } X s[i] = (char)NULL; X *R++ = atof(s); X if (*sp == ',') X ++sp; X } X X return(TRUE); X} X X Xchar * XSkipBlanks(s) Xregister char *s; X{ X while(isspace(*s)) X ++s; X return(s); X} X X Xvoid XPrintUsage(Fp, Usage, Function, Symbols) XFILE *Fp; Xchar *Usage[]; Xchar *Function[]; XARGDEF *Symbols[]; X{ X register int i; X X for (i=0; Usage[i]; i++) X fputs(Usage[i], Fp); X for (i=0; Function[i]; i++) X fputs(Function[i], Fp); X fprintf(Fp, "Options:\n"); X for (i=0; Symbols[i]; i++) { X fputc('\t', Fp); X PrintArgDef(Fp, Symbols[i]); X } X} X X Xbool XParseHelp(Usage, Function, Symbols, arg) Xchar *Usage; Xchar *Function; XARGDEF *Symbols[]; Xchar *arg; X{ X bool Help(); X char *EqualSign; X X if (strncmp(arg, "Help", 4)==0 || strncmp(arg, "help", 4)==0) { X if ((EqualSign = strchr(arg,'=')) == (char *)NULL) X return(Help(Usage, Function, Symbols, "All")); X else X return(Help(Usage, Function, Symbols, EqualSign+1)); X } X return(FALSE); X} X X Xbool XHelp(Usage, Function, Symbols, arg) Xchar *Usage[]; Xchar *Function[]; XARGDEF *Symbols[]; Xchar *arg; X{ X register int i, j; X extern VALUE V_Verbose; X X if (strcmp(arg, "All")==0 || strcmp(arg,"all")==0) { X if (VtoBoolean(V_Verbose)) { X for (i=0; Usage[i]; i++) X fputs(Usage[i], stdout); X for (i=0; Function[i]; i++) X fputs(Function[i], stdout); X fprintf(stdout, "Options:\n"); X for (i=0; Symbols[i]; i++) { X fputc('\t', stdout); X PrintArgDef(stdout, Symbols[i]); X if ( Symbols[i]->ad_helptext != (char **)NULL) { X for (j=0; Symbols[i]->ad_helptext[j]; j++) X fputs(Symbols[i]->ad_helptext[j], stdout); X } X fputc('\n', stdout); X } X } else { X fputs(Usage[0], stdout); X fputs(Function[0], stdout); X fprintf(stderr, "Options:\n"); X for (i=0; Symbols[i]; i++) { X fputc('\t', stdout); X PrintArgDef(stdout, Symbols[i]); X } X } X return(TRUE); X } else { X /* find entry in symbol table */ X for (i=0; Symbols[i]; i++) { X if (strcmp(arg,Symbols[i]->ad_id) == 0) { X /* found */ X fputc('\t', stdout); X PrintArgDef(stdout, Symbols[i]); X if (VtoBoolean(V_Verbose) && Symbols[i]->ad_helptext != (char **)NULL) { X for (j=0; Symbols[i]->ad_helptext[j]; j++) X fputs(Symbols[i]->ad_helptext[j], stdout); X fputc('\n', stdout); X } X return(TRUE); X } X } X } X return(FALSE); X} X X X X Xbool XParseArg(Symbols, arg) XARGDEF *Symbols[]; Xchar *arg; X{ X register int i; X char *EqualSign; X char *ValueStr; X int wid; X X if ((EqualSign = strchr(arg,'=')) == (char *)NULL) { X ValueStr = arg; X wid = strlen(ValueStr); X } else { X ValueStr = EqualSign + 1; X wid = EqualSign - arg; X } X X /* find entry in symbol table */ X for (i=0; Symbols[i]; i++) { X if (strncmp(arg,Symbols[i]->ad_id, wid) == 0) { X /* found */ X return(ParseEntry(Symbols[i], ValueStr)); X } X } X X return(FALSE); X} X X Xbool XParseEntry(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X char *StartOpt, *StartType; X char *BarOpt; X char *BarType; X int WidOpt, WidType; X X StartOpt = Entry->ad_options; X StartType = Entry->ad_opttype; X do { X if ((BarOpt = strchr(StartOpt,'|')) == (char *)NULL) { X WidOpt = strlen(StartOpt); X } else { X WidOpt = BarOpt - StartOpt; X } X if ((BarType = strchr(StartType,'|')) == (char *)NULL) { X WidType = strlen(StartType); X } else { X WidType = BarType - StartType; X } X X if (strncmp(StartType, "string", WidType) == 0) { X if (ParseString(Entry, StartOpt, WidOpt, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "dbl", WidType) == 0) { X if (ParseDbl(Entry, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "float", WidType) == 0) { X if (ParseFloat(Entry, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "int", WidType) == 0) { X if (ParseInt(Entry, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "boolean", WidType) == 0) { X if (ParseBool(Entry, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "byte", WidType) == 0) { X if (ParseByte(Entry, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "interval", WidType) == 0) { X if (ParseInterval(Entry, arg) == TRUE) X return(TRUE); X else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "set", min(WidType,3)) == 0) { X if (ParseSet(Entry, arg, StartType,WidType) == TRUE) { X return(TRUE); X } else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else if (strncmp(StartType, "rect", WidType) == 0) { X if (ParseRect(Entry, arg) == TRUE) { X return(TRUE); X } else { X StartOpt = ++BarOpt; X StartType = ++BarType; X continue; X } X } else { X fprintf(stderr, "Internal Error: invalid option type string: \"%s\"\n", StartType); X PrintArgDef(stderr,Entry); X errno = EINVAL; X exit(errno); X } X } while(StartOpt != (char)NULL && StartType != (char)NULL); X return(TRUE); X} X X Xbool XParseString(Entry, Option, n, arg) XARGDEF *Entry; Xchar *Option; Xint n; Xchar *arg; X{ X if (*Option == '*') { X /* Match any string */ X Entry->ad_value->val_type = string; X Entry->ad_value->val_u.udt_string = StrDup(arg); X return(TRUE); X } else if (arg!=(char *)NULL && strncmp(arg,Option,strlen(arg)) == 0) { X /* Matches option */ X Entry->ad_value->val_type = string; X Entry->ad_value->val_u.udt_string = StrDup(arg); X return(TRUE); X } else { X return(FALSE); X } X} X Xchar * XStrDup(Str) Xchar *Str; X{ X register int n; X register char *Dup; X X if (Str == (char *)NULL) X return((char *)NULL); X X n = strlen(Str); X if ((Dup = malloc(n+1)) == (char *)NULL) { X perror("(StrDup) "); X assert(Dup != (char *)NULL); X exit(errno); X } X memcpy(Dup, Str, n+1); X return(Dup); X} X X Xbool XParseDbl(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetDbl(Entry->ad_value, arg)); X} X Xbool XParseFloat(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetFloat(Entry->ad_value, arg)); X} X Xbool XParseInt(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetInt(Entry->ad_value, arg)); X} X Xbool XParseBool(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetBool(Entry->ad_value, arg)); X} X Xbool XParseByte(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetByte(Entry->ad_value, arg)); X} X Xbool XParseInterval(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetInterval(Entry->ad_value, arg)); X} X Xbool XParseSet(Entry, arg, Type, WidType) XARGDEF *Entry; Xchar *arg; Xchar *Type; Xint WidType; X{ X return(SetSet(Entry->ad_value, arg, Type, WidType)); X} X Xbool XParseRect(Entry, arg) XARGDEF *Entry; Xchar *arg; X{ X return(SetRect(Entry->ad_value, arg)); X} X X Xvoid XPrintArgDef(Fp, Def) XFILE *Fp; XARGDEF *Def; X{ X fprintf(Fp, "%s=", Def->ad_id); X fprintf(Fp, "[%s]", Def->ad_options); X fprintf(Fp, " default: %s\n", Def->ad_default); X fflush(Fp); X} X X Xvoid XPrintArg(Fp, Def) XFILE *Fp; XARGDEF *Def; X{ X LATOM *A; X X switch(Def->ad_value->val_type) { X default: X fprintf(Fp,"%s=!\n", Def->ad_id); X break; X case boolean: X fprintf(Fp,"%s=%s\n", X Def->ad_id, X Def->ad_value->val_u.udt_bool? "TRUE":"FALSE"); X break; X case integer: X fprintf(Fp,"%s=%d\n",Def->ad_id,Def->ad_value->val_u.udt_int); X break; X case dbl: X fprintf(Fp,"%s=%lg\n",Def->ad_id,Def->ad_value->val_u.udt_dbl); X break; X case flt: X fprintf(Fp,"%s=%g\n",Def->ad_id,Def->ad_value->val_u.udt_flt); X break; X case byte: X fprintf(Fp,"%s=%c\n",Def->ad_id,Def->ad_value->val_u.udt_byte); X break; X case string: X fprintf(Fp,"%s=\"%s\"\n",Def->ad_id,Def->ad_value->val_u.udt_string); X break; X case interval: X fprintf(Fp,"%s=%g,%g\n",Def->ad_id,Def->ad_value->val_u.udt_interval); X break; X case set: X fprintf(Fp,"%s={\n",Def->ad_id); X for (A=Def->ad_value->val_u.udt_set.list_head; A; A=A->la_next) X if (A->la_next) X fprintf(Fp,"\t\t<%s>,\n",(char *)A->la_p); X else X fprintf(Fp,"\t\t<%s>\n",(char *)A->la_p); X fprintf(Fp, "\t}\n"); X break; X case rect: X fprintf( X Fp, X "%s={%g,%g, %g,%g}\n", X Def->ad_id, X Def->ad_value->val_u.udt_rect.r_diag[0], X Def->ad_value->val_u.udt_rect.r_diag[1], X Def->ad_value->val_u.udt_rect.r_diag[2], X Def->ad_value->val_u.udt_rect.r_diag[3] X ); X break; X } X} END_OF_FILE if test 14827 -ne `wc -c <'Csrc/get_args.c'`; then echo shar: \"'Csrc/get_args.c'\" unpacked with wrong size! fi chmod +x 'Csrc/get_args.c' # end of 'Csrc/get_args.c' fi if test -f 'docs/ListPlot.uu' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'docs/ListPlot.uu'\" else echo shar: Extracting \"'docs/ListPlot.uu'\" \(19126 characters\) sed "s/^X//" >'docs/ListPlot.uu' <<'END_OF_FILE' Xbegin 600 ListPlot.man XM"B`@("`@3&ES=%!L;W0H,2D@("`@("`@("`@("`@("`@("!!34E'02!-86YUW XM86P@("`@("`@("`@("`@("`@("!,:7-T4&QO="@Q*0H*"@H@("`@()LQ;4Y!: XM344@"B`@("`@("`@("";,&U,:7-T4&QO="`M(&$@=F%N:6QL82!P;&]T=&ENN XM9R!F:6QT97(@"@H@("`@()LQ;5-93D]04TE3(`H@("`@("`@("`@3&ES=%!LD XM;W0@FS!M6R!O<'1I;VYS(%T@"@H@("`@()LQ;41%4T-225!424].(`H@("`@Z XM("`@("`@FS!MFS-M3&ES=%!L;W0@()LP;6$@('-I;7!L92`@,D0@('!L;W1TZ XM:6YG(&9I;'1E XM:&4*("`@("`@("`@('!R;V=R86T@86-C97!T65S*2X@(`H*("`@("`@("`@()LQ;5-T'!E8W0@"X@V XM07-P96-T4F%T:6\],2XP*2X@(`H*("`@("`@("`@()LQ;4EN=&5R=F%LH)LP_ XM;:!V86QU97,@97AP96-T(&$@<&%IWTI+B`@("`H97@N"B`@("`@("`@("`@("`@("`@("`@3&EN95-T>6QE- XM/7M-4RQ-35,L35-M;5-]*2`*"B`@("`@("`@("";,6U296-TH)LP;:"@H*"@# XM=F%L=65S("!E>'!E8W0@(&$@(&QIS`N,2PP+C,L"B`@("`@("`@("`@("`@("`@("`@,"XY+#`N-GTI+B`@+ XM"@H*("`@("`@("`@(%1H92`@=&ET;&4@(&%N9"`@;&%B96P@=F%R:6%B;&5SM XM(&%C8V5P="!S=')I;F=S('1H870@:6YC;'5D90H@("`@("`@("`@=&AE(&9O/ XM;&QO=VEN9R!C;VYT XM*2`*"@H@("`@(#4O,34O.3`@("`@("`@("`@("`@("`@("`@("`@("`@("TQ' XM+2`@("`@("`@("`@("`@("`@("!$=6ME(%5N:79E2!B\ XM90H@("`@("`@("`@9VEV96XN("!!('-T&5S+B`@268@('-E="`@=&AIF XM2X@(`H*("`@) XM("`@("`@()LQ;41O;6%I;ILP;3U;()LS;6EN=&5R=F%L()LP;7P@FS%M06QL' XM()LP;7P@FS%M075T;VUA=&EC()LP;5T@"B`@("`@("`@("`@("`@("`@("`@S XMFS-M1&]M86EN("";,&UM87D@8F4@=7-E9"!T;R!S<&5C:69Y('1H92!B;W5N5 XM9',@;VX@=&AE(%@*("`@("`@("`@("`@("`@("`@("!A>&ES+B`@5VAE;B!S_ XM970@=&\@FS%M06QLFS!M+"!A;&P@('!O:6YT'0@(&9O&ES(&QA8F5L7!I8V%L"B`@("`@("`@("`@("`@("`@("`@ XM72`*("`@("`@("`@("`@("`@("`@("";,VU,:6YE0V]L;W(@FS!M;6%Y(&)E/ XM('5S960@=&\@2!A("!L:7-T("!O9B`@;&EN90H*"B`@("`@-2\QT XM-2\Y,"`@("`@("`@("`@("`@("`@("`@("`@("`@+3(M("`@("`@("`@("`@9 XM("`@("`@($1U:V4@56YI=F5R0H*"B`@("`@3&ES=%!L;W0H,2D@("`@& XM("`@("`@("`@("`@("!!34E'02!-86YU86P@("`@("`@("`@("`@("`@("!,I XM:7-T4&QO="@Q*0H*"B`@("`@("`@("`@("`@("`@("`@8V]L;W)S("!F;W(@( XM('!L;W1S("!W:71H("!M=6QT:7!L92`@8W5R=F5S(&EF('1H:7,*("`@("`@C XM("`@("`@("`@("`@("!F96%T=7)E("!I XM;W(@<&]R=')A:70@;W)I96YT871I;VXN("`*"B`@("`@("`@("";,6U/&5S(&%T(&%NU XM"B`@("`@("`@("`@("`@("`@("`@87)B:71R87)Y('!O:6YT+B`@5&AE()LSA XM;4UE9&EA;B";,&UV86QU92!P;&%C97,@=&AE(&%X97,*("`@("`@("`@("`@$ XM("`@("`@("!A="!T:&4@;65D:6%N()LS;5@@FS!M86YD("!T:&4@(&UE9&EA# XM;B`@FS-M62`@FS!M;V8@('1H92`@9&%T80H@("`@("`@("`@("`@("`@("`@4 XM('9A;'5E6UB;VQS< XM('1O(&)E('!L;W1T960@:6X*("`@("`@("`@("`@("`@("`@("!T:&4@8W5RR XM6UB;VP@6UB;VR;,&T]6R";,6U!=71O;6%T:6,@FS!M?"";,VUS+ XM970@FS!M72`*("`@("`@("`@("`@("`@("`@("";,VU0;VEN=%-Y;6)O;"";N XM,&US<&5C:69I97,@82!L:7-T(&]F('-Y;6)O;',@=&\@8F4@=7-E9`H@("`@8 XM("`@("`@("`@("`@("`@('=H96X@<&QO='1I;F<@(&1A=&$@<&]I;G1S+B`@( XM5&AE('-Y;6)O;',@='EP97,@87)E"B`@("`@("`@("`@("`@("`@("`@96YCW XM;V1E9"!A2`@8F4*("`@("`@("`@("`@8 XM("`@("`@("!I;F-L=61E9"X@(`H*"@H@("`@(#4O,34O.3`@("`@("`@("`@@ XM("`@("`@("`@("`@("`@("TS+2`@("`@("`@("`@("`@("`@("!$=6ME(%5N9 XM:79E7!E+B`@S XM"@H@("`@("`@("`@FS%M4&QO=%1Y<&6;,&T]6R";,6UL:6YL:6X@FS!M?"";, XM,6UL;V=L:6X@FS!M?"";,6UL:6YL;V<@FS!M?"";,6UL;V=L;V<@FS!M?"";5 XM,6UP;VQA7!E7 XM("";,&US<&5C:69I97,@=&AE()LS;6=R87!H('!A<&5R()LP;75P;VX@=VAI[ XM8V@@=&AE"B`@("`@("`@("`@("`@("`@("`@<&QO="!I0H@("`@("`@("`@("`@= XM("`@("`@('=H971H97(@=&AE(&EN9&5P96YD96YT("!V87)I86)L92`@:7,@H XM(&%N9W5L87(@(&]R"B`@("`@("`@("`@("`@("`@("`@&ES("`@8F]U0 XM;F1S+B`@("`H97@N"B`@("`@("`@("`@("`@("`@("`@4F%N9V4]+3$L,2`I> XM(%=H96X@('-E="`@=&\@()LQ;4%L;)LP;2P@(&%L;"`@<&]I;G1S("!A2!N;W0@8F4@<&QO='1E9"X@(`H*("`@("`@("`@()LQ;5-U> XM8E!A9V5SFS!M/5L@FS-M:6YT97)V86P@FS!M72`*("`@("`@("`@("`@("`@A XM("`@("";,VU3=6)086=E2`@=7-E("!W? XM:71H:6X@('1H92`@8V]N=&5X="`@;V8*("`@("`@("`@("`@("`@("`@("";< XM,VU,:7-T4&QO="X@()LP;4ET("!M:6=H="!B92!UF4@;V8@=&AE('!L] XM;W1S(&)U="!T:&4@FS-M5FEE=U!OF4@;V8@=&AE('1I=&QE"B`@("`@("`@("`@9 XM("`@("`@("`@=&5X="X@(`H*("`@("`@("`@()LQ;55S94EN<'5T1FEL99LPH XM;3U;("H@72`*("`@("`@("`@("`@("`@("`@("";,VU56]U('=O=6QD(')A=&AE'1E;F1E9"!M97-S86=I;F"X@(%9I97=0;W)T/7LP+C$L,"XS+"`P+CDL,"XV?2`*"B`@("`@("`@C XM("";,6U83&%B96R;,&T]6R`J(%T@"B`@("`@("`@("`@("`@("`@("`@FS-MM XM6$QA8F5L()LP;7-P96-I9FEE'0@+ XM(&-O;G1R;VP*("`@("`@("`@("`@("`@("`@("!S97%U96YC97,@9&5S8W)I1 XM8F5D(&%B;W9E(&UA>2!B92!I;F-L=61E9"X@(`H*("`@("`@("`@()LQ;5E,N XM86)E;)LP;3U;("H@72`*("`@("`@("`@("`@("`@("`@("";,VU93&%B96P@I XMFS!M&ES("!L86)E;"X@("`@5&5X="`@8V]N=')OI XM;`H@("`@("`@("`@("`@("`@("`@('-E<75E;F-E XM=&AE(&YU;6)E"X*("`@("`@("`@("`@("`@("`@("";,VU85&EC:STP+C$L,3`@FS!ML XM:6YD:6-A=&5S(&UA:F]R('1I8VMS(&%T('5N:71S(&]F(#`N,0H@("`@("`@! XM("`@("`@("`@("`@('=I=&@@,3`@;6EN;W(@2P@($1U2!-+B!2:6-H87)D. Mail comments to the moderator at . Post requests for sources, and general discussion to comp.sys.amiga.