Mercurial > hg > aim92
diff model/gen.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/model/gen.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,1548 @@ +/* + Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 + =========================================================================== + + Permission to use, copy, modify, and distribute this software without fee + is hereby granted for research purposes, provided that this copyright + notice appears in all copies and in all supporting documentation, and that + the software is not redistributed for any fee (except for a nominal shipping + charge). Anyone wanting to incorporate all or part of this software in a + commercial product must obtain a license from the Medical Research Council. + + The MRC makes no representations about the suitability of this + software for any purpose. It is provided "as is" without express or implied + warranty. + +*/ + +/* + gen.c + ===== + + APU, ASP model demonstration program. + + + Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit. + + + Authors : John Holdsworth (1989), Mike Allerhand (1990) + + + Edited : M.Akeroyd 22-1-1993 + Removed the conditional of `if (centering) Clear (w)' + (in plot_frame), so that Clear may be called for + PostScriptWindows that AREN'T centered, so allowing + showpages to be generated. + See also edit to ps.c + + : M Akeroyd 3-8-1993 + Added new options: + erbscale_efb (InputOption) mono_ctn (SilentOption) + colour_ctn (SilentOption) planemask_ctn (SilentOption) + Allowed "bitmap=stdout". + + : MAA 3rd August 1993 + Extra options + framenumber (SilentOption), review (SilentOption) + + : MAA 22nd July 1994. + Extra postscript options ALl silent + xstart_ps xend_ps ystart_ps yend_ps + xtitle_ps ytitle_ps + Extra X options + fg_col bg_col + + : MAA Summer 1984. Lots of postscript options. All silent + portraitstr, landscapestr; + fontnamestr, fontsizestr; + xmajorticksstr, xminorticksstr, ymajorticksstr, yminorticksstr; + axistop, axisbottom, axisleft, axisright; + + : AJD Spring 1995. + Added a new argument 'nwid' to the function SourceDraw, so that genspl + can have the necessary information. + + : AJD May, 1995. + Made options overlap, headroom, perspective, bytemax and type silent. +*/ + + +#ifndef lint +static char *sccs_id = "@(#)gen.c 1.66 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 6/6/91" ; +#endif + + +/**************************************************************************** +* This module contains: +* Display option parameter strings. +* Model option parameter strings. +* File-format strings. +* X windows interface, (included from windows.h). +* Options handler routines, (included from options.h). +* Option defaults, (application specific). +* Strings for generic option types, (OnOption etc). +* Display options table, (displayopts[]). +* Model option tables, (included from table.c). +* Model entry-point functions, (included from model.c). +* Display drawing routines, (included from draw.h and fill.h). +* Options table construction, (constructOptions(), and mapOptions()). +* Main. +****************************************************************************/ + +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <math.h> + +#if defined(THINK_C) || defined(NeXT) +#include <stdlib.h> +#endif + +/********************* Display option parameter strings ********************* +* The strings defined here are pointers referenced by the "value" field in +* the display options table, displayopts. They are assigned to space which +* initially contains defaults in the "defaultValue" field of the display +* options table. +****************************************************************************/ + +static char *bmaxstr, *topstr, *botstr, *overstr ; +static char *headstr, *downcstr, *heightstr, *helpstr ; +static char *invertstr, *lengthstr, *linstr, *outstr ; +static char *reusestr, *startstr, *envstr, *typestr ; +#ifdef X11 +static char *dispstr, *erasestr, *hiddenstr, *bitmapstr ; +static char *kludgestr, *magstr, *penstr, *psfilestr ; +static char *psstr, *animstr, *titlestr, *viewstr ; +static char *widthstr, *xstr, *ystr ; +/* All these MAA. */ +char *monostr, *colourstr, *planemaskstr, *rotateaxesstr; +char *fgcolourstr, *bgcolourstr; +char *xstartstr, *ystartstr, *xendstr, *yendstr; +char *xnewtitlestr, *ynewtitlestr; +char *portraitstr, *landscapestr; +char *fontnamestr, *fontsizestr, *titlesizestr; +char *xticksstr, *yticksstr, *outsidestr; +char *axistopstr, *axisbottomstr, *axisleftstr, *axisrightstr; +char *xmajorticksstr, *xminorticksstr, *ymajorticksstr, *yminorticksstr; +char *axislinewidthstr, *figurelinewidthstr; +char *boxstr; +#endif /* X11 */ + +char *framenumberstr, *reviewstr; /* MAA: 3-8-1993 */ + +static char *test1str, *test2str, *test3str, *test4str ; + +char headerstr[64] ; + +char *filestr ; + +/* application display parameters */ + +#ifdef X11 +static char *tiltstr = "0." ; +static char *diststr = "0.5" ; +static char *roomstr = "0%" ; +#endif /* X11 */ + +/*************** Included from glib (graphics library) directory ***********/ + +#include "options.h" +#include "defaults.h" + +#ifdef X11 +#include "windows.h" +#endif /* X11 */ + +/******************* Strings for generic option values ********************** +* Generic option values, (ON_OPTION etc), are defined in options.h. +* Convenience routines used to test or convert option values are: +* OptionStringsEqual( str1, str2 ) -(defined in options.c). +* isON( str ) -(defined in options.h). +* isOFF( str ) -(defined in options.c). +* isNULL( str ) -(defined in options.c). +* OptionInt( str ) -(defined in model.c). +* OptionDouble( str ) -(defined in model.c). +* Samples( str ) -(defined in model.c). +* Cycles( str, cfreq ) -(defined in model.c). +* Scalar( str ) -(defined in model.c). +* Freq( str ) -(defined in model.c). +* +****************************************************************************/ + + +static char helpstring[200] = "no help initially" ; +static char OnOption[] = ON_OPTION ; /* "on" */ +static char OffOption[] = OFF_OPTION ; /* "off" */ +static char NullOption[] = NULL_OPTION ; /* "none" */ +static char CenterStr[] = "center" ; +static char LengthStr[] = "remainder" ; +static char LandStr[] = "landscape" ; + +static int isEXCITE( str ) +char *str ; +{ + return ( strncmp( str, "excitation", strlen( str ) ) == 0 ) ; +} + +static int isWATERFALL( str ) +char *str ; +{ + return ( strncmp( str, "waterfall", strlen( str ) ) == 0 ) ; +} + +static int isGREYSCALE( str ) +char *str ; +{ + return ( strncmp( str, "greyscale", strlen( str ) ) == 0 || + strncmp( str, "grayscale", strlen( str ) ) == 0 ) ; +} + + + +/************************* Options table *********************************** +* The complete options table is built by constructOptions() according to the +* application. It is composed of the display options, (displayopts[], below), +* and the model option tables (from table.c) which are appropriate for the +* application. The sequence of processing stages, (and hence model option +* tables), for an application is determined by FindStage() in model.c. +* +* The complete options table is an array of Option structs. +* The Option struct is defined in options.h as: +* +* typedef struct { +* char *name ; The name of the option. +* char *defaultValue ; Default value. +* char **value ; Address of current value. +* char *comment ; Something to print when the user types "-help". +* short classification ; Type of option it is. +* } Option; +* +* The classification of options uses names defined in options.h: +* InputOption +* OutputOption +* InOutOption +* SilentOption +* +* Routines which access the option table: +* Note: Some routines are called to supply arguments to other routines. +* Routines which access the option table in some way are denoted (*). +* Most of these routines are defined in options.c. +* +* main() +* | +* +-----------------+-----------+----+-------+-----------------+ +* | | | | | +* | | | ModeledSource() | +* | | | | | +* | | | checkForFile() | +* helpopts() | | | | +* | | +---+---+ | +* | | | | +* | getopts() readopts() writeopts() +* | | | | +* | getnopts(*) readnopts() writenopts(*) +* | [arg countOptions(*)] [arg countOptions(*)] [arg countOptions(*)] +* | | | | +* | +-------+------+ | countBytesToWrite(*) +* | | | | | +* | | | +------+------+ +* | | | | +* | | | processOptionFile() +* | | | | +* | | +------+------+ +* | | | +* | | LookUpAndStore(*) +* | | | +* | | +---+---+----------+ +* | | | | | +* | +-----+----+ LookUp(*) Ambiguity(*) +* | | | +* +----+----+ updateOptionsFile(*) +* | +* defaultHelpHandler(*) +* +* +* getopts() +* Operates on the options table given to it as an argument. +* a) Each "value" field is initialized to its "defaultValue" field. +* b) The "value" fields are re-initialized by any corresponding values found +* in the options ("rc") file, (overriding the "defaultValue"). +* c) The "value" fields are re-initialized again by any corresponding values +* found in command-line arguments. +* d) Special arguments are dealt with: +* "help" calls the onLineHelpHandler() routine, (see below). +* "update" calls the updateOptionsFile() routine. +* e) Return the remainder of the command-line (argc and argv) for use in +* main(). +* +* helpopts() +* Is called to print the help menu if no input file has been found by +* getopts(), (in the "rc" file), and none remains on the command-line. +* An alias for the onLineHelpHandler() function, which is in turn an +* alias for the defaultHelpHandler() routine, (see options.c). +* +* readopts() +* Read any options header which may be at the start of the input file. +* Interpret the header like an options ("rc") file, and re-initialize any +* corresponding "value" fields in the given options table, (as in getopts()). +* Skip to the start of the input data, allowing for any offset (ie startstr). +* +* writeopts() +* Write the given options table as an options header at the start of an o/p +* file, if the "header" option is "on". +* +****************************************************************************/ + +static Option *options; + +/******************** Display options table ******************************** +* Options table for application display parameters. +****************************************************************************/ + +static Option displayopts[] = { + + /* Miscellaneous Silent Parameters (hidden from users) */ + + + { "Version", headerstr, &versionstr, "Version number and date", OutputOption}, + + { "test1", "0", &test1str, "Dummy option for test and development", SilentOption}, + { "test2", "0", &test2str, "Dummy option for test and development", SilentOption}, + { "test3", "0", &test3str, "Dummy option for test and development", SilentOption}, + { "test4", "0", &test4str, "Dummy option for test and development", SilentOption}, + + { "linear_sgm", OffOption, &linstr, "Linear frequency axis for spectrograms",SilentOption}, + { "useprevious", OffOption, &reusestr, "Use previously stored output", SilentOption}, + +/* MAA: 21-8-1993 + * These next two options are here, because otherwise "gensgm -use ..." (at least) core dumps. + */ + { "framenumber", OffOption, &framenumberstr, "Index of current frame (to stderr)\n", SilentOption}, + { "review", OffOption, &reviewstr, "Wait for keyboard <return> between frames",SilentOption}, + +#ifdef X11 + { "pstofile", OffOption, &psfilestr, "Send PostScript output to .ps file", SilentOption}, + { "invert", OffOption, &invertstr, "Invert axis of sai image", SilentOption}, + { "fast", OffOption, &kludgestr, "Speed up image generation", SilentOption}, +#endif /* X11 */ + + /* ( The order of the "help" option members is strange due to the way */ + /* it was originally used. See options.c: defaultHelpHandler() and */ + /* updateOptionsFile() ). */ + + /* Input Parameters */ + + { "envelope", OffOption, &envstr, "Type of model to use required", SilentOption}, + { "help", "not used", &helpstr, helpstring, SilentOption}, + +#ifdef X11 + + /* Screen Output Parameters */ + + { "title", "filename", &titlestr, "Title of picture, or input filename", InputOption}, +#ifdef THINK_C + { "x0_win", "10", &xstr, "Left edge of window (pixels)", InOutOption}, + { "y0_win", "50", &ystr, "Lower edge of window (pixels)", InOutOption}, +#else + { "x0_win", CenterStr, &xstr, "Left edge of window (pixels)", InOutOption}, + { "y0_win", CenterStr, &ystr, "Lower edge of window (pixels)", InOutOption}, +#endif +#ifdef PC + { "width_win", "400", &widthstr, "Window width (pixels)", InOutOption}, + { "height_win", "300", &heightstr, "Window height (pixels)\n", InOutOption}, +#else /* UNIX */ + { "width_win", "540", &widthstr, "Window width (pixels)", InOutOption}, + { "height_win", "400", &heightstr, "Window height (pixels)\n", InOutOption}, +#endif + { "display", OnOption, &dispstr, "Select display of output image", InOutOption}, + { "view", LandStr, &viewstr, "Select display format", InOutOption}, + { "top", "1024", &topstr, "Maximum of plotted range", InputOption}, + { "bottom", "-1024", &botstr, "Minimum of plotted range", InputOption}, + { "overlap", "50%", &overstr, "Overlap between channels", SilentOption}, /* AJD 16-5-95 */ + { "headroom", "0%", &roomstr, "Headroom at top of picture", SilentOption}, /* AJD 16-5-95 */ + { "magnification", "1", &magstr, "Magnification of image in display", InputOption}, + { "pensize", "1", &penstr, "Size of plotted lines and dots", InputOption}, + { "hiddenline", OnOption, &hiddenstr, "Hidden line removal\n", InputOption}, + { "perspective", "0", &tiltstr, "Perspective view of display (degrees)\n", SilentOption}, /* AJD 16-5-95 */ +#endif /* X11 */ + + { "downchannel", OffOption, &downcstr, "Average adjacent frequency channels\n", InOutOption}, + +#ifdef X11 + + /* Auditory image cartoon parameters */ + + { "erase_ctn", OnOption, &erasestr, "Erase display between cartoon frames", InOutOption}, + { "animate_ctn", OffOption, &animstr, "Animate cartoon", InOutOption}, + { "bitmap_ctn", OffOption, &bitmapstr, "Produce cartoon output (.ctn)\n", InputOption}, + { "mono_ctn", OnOption, &monostr, "Force monochrome (single plane) cartoons.", SilentOption}, + { "colour_ctn", OffOption, &colourstr, "Force colour (multi-plane) cartoons.", SilentOption}, + {"planemask_ctn", "1", &planemaskstr, "Planemask for creating cartoons.\n", SilentOption}, + {"fg_col", "black", &fgcolourstr, "Foreground Colour.\n", SilentOption}, + {"bg_col", "white", &bgcolourstr, "Background Colour.\n", SilentOption}, + + + /* Postscript options */ + + { "postscript", OffOption, &psstr, "Produce postscript output", InputOption}, + { "rotateaxes", OffOption, &rotateaxesstr, "Rotate the axes labels in .ps output", SilentOption}, + { "xstart_ps", "", &xstartstr, "Postscript x-axis: start point.", SilentOption}, + { "xend_ps", "", &xendstr, "Postscript x-axis: end point.", SilentOption}, + { "ystart_ps", "", &ystartstr, "Postscript y-axis: start point.", SilentOption}, + { "yend_ps", "", ¥dstr, "Postscript y-axis: end point.", SilentOption}, + { "xtitle_ps", "", &xnewtitlestr, "Postscript x-axis: title.", SilentOption}, + { "ytitle_ps", "", &ynewtitlestr, "Postscript x-axis: title.", SilentOption}, + { "portrait_ps", "", &portraitstr, "Use 'portrait' page format", SilentOption}, + { "landscape_ps", "", &landscapestr, "Use 'landscape' page format (overrides 'portriat)", SilentOption}, + { "fontname_ps", "Helvetica", &fontnamestr, "Define font", SilentOption}, + { "fontsize_ps", "12", &fontsizestr, "Define fontsize (points)", SilentOption}, + { "fonttitlesize_ps", "0", &titlesizestr, "Define fontsize for title (points)", SilentOption}, + { "axislinewidth_ps", "1", &axislinewidthstr, "Linewidth for axes & tickmarks (points)", SilentOption}, + { "figurelinewidth_ps", "1", &figurelinewidthstr, "Linewidth for figures (points)", SilentOption}, + { "xticks_ps", "6", &xticksstr, "Define size of x-axis (big) ticks (points)", SilentOption}, + { "yticks_ps", "6", &yticksstr, "Define size of y-axis (big) ticks' (points)", SilentOption}, + { "outsideticks_ps",OnOption, &outsidestr, "Print tick-marks 'outside' figure", SilentOption}, + { "axistop_ps", OnOption, &axistopstr, "Print tick-marks on top side", SilentOption}, + { "axisbottom_ps", OnOption, &axisbottomstr, "Print tick-marks on bottom side", SilentOption}, + { "axisleft_ps", OnOption, &axisleftstr, "Print tick-marks on left side", SilentOption}, + { "axisright_ps", OnOption, &axisrightstr, "Print tick-marks on right side", SilentOption}, + { "xmajorticks_ps", "1", &xmajorticksstr, "Relative *spacing* of ticks", SilentOption}, + { "xminorticks_ps", "1", &xminorticksstr, "Relative *spacing* of ticks", SilentOption}, + { "ymajorticks_ps", "1", &ymajorticksstr, "Relative *spacing* of ticks", SilentOption}, + { "yminorticks_ps", "1", &yminorticksstr, "Relative *spacing* of ticks", SilentOption}, + { "box_ps", OnOption, &boxstr, "Plot a box", SilentOption}, +#endif /* X11 */ + + /* File Output Parameters */ + { "output", OffOption, &outstr, "Produce output file", InputOption}, + { "header", OnOption, &headstr, "Add a header to the output file\n", InOutOption}, + { "bytemax", "255", &bmaxstr, "Maximum value in byte output", SilentOption}, /* AJD 16-5-95 */ + { "type", "short", &typestr, "Output data type\n", SilentOption}, /* AJD 16-5-95 */ + + { "input_wave", NullOption, &filestr, "Default input file name", InputOption}, + { "start_wave", "0ms", &startstr, "Start point in wave (ms)", InputOption}, + { "length_wave", LengthStr, &lengthstr, "Length of wave to process (ms)", InputOption}, + + ( char * ) 0 } ; + + +/*********************** Included from stitch directory ********************/ + +/* interfaces to stitch system */ + +#include "stitch.h" +#include "source.h" +#include "spiral.h" +#include "image.h" +#include "model.h" +#include "units.h" +#include "calc.h" +#include "ops.h" +#include "io.h" + + +#ifdef X11 +#include "draw.h" +#include "fill.h" +#endif /* X11 */ + +/**************************************************************************/ + +char *AlterSuffix() ; /* alter suffix of file name. */ +#ifdef X11 +void save_frame(), plot_frame() ; /* draw callbacks. */ +void fast_frame() ; +#endif /* X11 */ + +extern char *genstate() ; +static char *gen_state ; + +Source DownChannel() ; /* reduce channels by averaging. */ +#ifdef X11 +Source PackShorts() ; /* pack output into one byte. */ +#endif /* X11 */ +Source checkForFile() ; /* create source from file if present. */ + +#define POSTSCRIPT_FILE_SUFFIX ".ps" +#define CARTOON_FILE_SUFFIX ".ctn" + +#ifdef X11 +static WindowObject display = 0 ; +#endif /* X11 */ + +/***************************************************************************/ + +/* Return length of the file in bytes */ +static long fileLength( fp ) +FILE *fp ; +{ + long posn = ftell( fp ) ; + long length = 0 ; + + if( fseek( fp, 0l, 2 ) == 0 ) { + + length = ftell( fp ) ; + + (void) fseek( fp, posn, 0 ) ; + } + + return ( length ) ; +} + +/* per frame image handling */ + +static FILE *inputFilePointer = ( FILE * ) 0 ; + +#ifdef X11 + +static FILE *imageFilePointer = ( FILE * ) 0 ; +static int images = 0 ; +static void (*frame_drawer)() ; + +/***** axis information *****/ +/* + "Axis" is defined in windows.h:143 + The postscript program for drawing axis stuff is in axis.h +*/ + +static int Top() +{ + return ( atof( topstr ) / atof( magstr ) + 0.5 ) ; +} + +static int Bot() +{ + if( atof( botstr ) < 0 ) + return ( atof( botstr ) / atof( magstr ) - 0.5 ) ; + else + return ( atof( botstr ) / atof( magstr ) + 0.5 ) ; +} + +static struct { + double min, max ; + char *label ; +} xaxis, yaxis ; + + + +TimeAxis( min, max, label ) +double *min, *max ; +char **label ; +{ + *min = Samples( startstr, Samplerate() ) / Samplerate() ; + *max = Samples( startstr, Samplerate() ) / Samplerate() + Frames() * Framestep() / Samplerate() ; + + if( *max > 1. ) + *label = "Time [s]" ; + else { + *label = "Time [ms]" ; + + *min *= 1000. ; + *max *= 1000. ; + } +} + +MagnitudeAxis( min, max, label ) +double *min, *max ; +char **label ; +{ + *min = Bot() ; + *max = Top() / ( 1. - atof( headstr ) / 100. ) ; + + *label = "Magnitude" ; +} + + +static void DrawAxes( win ) +WindowObject win ; +{ + /* frame window with axes */ + + Axes( win, titlestr, xaxis.min, xaxis.max, xaxis.label, + yaxis.min, yaxis.max, yaxis.label ) ; + return ; +} + +#endif /* X11 */ + +/******************************* main ************************************** +* The following tables are used extensively: +* stage table Arrays of _stage structs, ("envelope", "fine", etc.), defined +* in routine FindStage() in model.c. +* option table Array of Option structs built at run-time by +* constructOptions() from displayopts, (in gen.c), and tables of +* model options included from table.c. +* +* Compiler switches for model versions are: +* FLOAT For floating point version, (default uses integer arithmetic). +* Defined in calc.h. +* +* The model version number is the sccs <release-number>.<level-number> of +* the file version.c. Refer to that file for incrementing the version number. +* The version number is stored in versionstr in routine getversion(). +****************************************************************************/ + +int argc_save ; +char **argv_save ; + +main( argc, argv ) +int argc ; +char *argv[] ; +#ifdef THINK_C +{ + static char *realargv[] = { "prog", "", 0 }; + static char *progs = { "\pgenwav;-;\ +genfbm;genfbr;genfbc;genfbt;genfbd;gensai;genspl;gensas;-;\ +genbmm;gennap;gensai;-;gensgm;gencgm;gensas;-;genasa;genepn;gensep;-;Quit/Q" } ; + + extern char *MacMenu(), *MacFile() ; + + MacInit() ; + + realargv[0] = MacMenu(progs) ; + realargv[1] = MacFile() ; + + return ( real_main( sizeof( realargv ) / sizeof (*realargv) - 1, realargv ) ) ; +} + +real_main( argc, argv ) +int argc ; +char *argv[] ; +#endif +{ + int i ; + FILE *ofp = 0 ; + Source source ; + char *which, *psfilename ; + char title[256] ; + char *programName ; + int x, y, pixels, image, time ; + long headerSize, fileFramebytes ; + double *frequency_scale ; +#ifdef X11 + WindowObject psw = 0 ; + char *imageFileName ; +#endif /* X11 */ + +/************************************************************************** +* Determine which version of the model is required. +* Set "which" to the last three chars of the program name, (allowing for +* a ".exe" extension in the case of a PC version). +**************************************************************************/ + + + programName = argv[0] ; + + which = programName + strlen( programName ) - strlen( "xxx" ) ; + +#ifdef PC + lowerArgs( argv, argc ) ; + + which -= strlen( ".exe" ) ; +#endif + + +/*************************************************************************** +* Process arguments, (the model options): +* Set option defaults (from option table in model.c). +* Then override these by any options in the options file, +* (the resource control file, eg .gensairc). +* Finally, override these by any options given as command-line arguments. +* +* offsetOptions() finds the first option, (a ptr to one line of the "res" +* array), required by the program. This gives a place mark in the options +* table. (Note that the bottom of the options table, a null, corresponds with +* the top of the help menu). +* This first option appropriate to the program is found by looking it up in +* the stage table (in model.c), and then cross-referencing the option name +* with the names in the options table. +* +* Here is an example of an option, showing the members of the Options struct: +* name: defaultValue: value: comment: classification: +* {"length_wave", LengthStr, &lengthstr, "Length of wave", InputOption}, +* +* getopts() operates on the options between the given place mark and the +* bottom of the table. +* This is the only call to routine getopts(), which is defined in options.c. +* First, each "value" is set to its corresponding "defaultvalue". +* Then the options file (the "rc" file) is opened, and any options found there +* are assigned to the corresponding "value", (overriding the "defaultvalue"). +* Then the command-line arguments are examined, and any options found there +* are assigned to the corresponding "value", (overriding again). +* Special arguments are dealt with: +* "help" calls the onLineHelpHandler() routine, (see below). +* "update" calls the updateOptionsFile() routine. +* +* Finally, leave the remainder of the command line (argc and argv). +* Anything left on the command line is interpreted as follows: +* "filestr" is the input data filename, +* "startstr" is the start point in the data, +* "lengthstr" is the amount of data to process, +* "whichstr" is the last 3 chars of the program name (the program version). +* +* Note that if no input file has been found by getopts(), (in the "rc" file), +* and none remains on the command line, then helpopts() is called. +* This is an alias for the onLineHelpHandler() function, which is in turn an +* alias for the defaultHelpHandler() routine, (see options.c). +* +* +***************************************************************************/ + + getversion( programName ) ; + + /* The helpstring, defined in model.c, is stored as the comment field */ + /* of the help option (see table.c). It is accessed in options.c in */ + /* defaultHelpHandler(), using options[help].comment. */ + + (void) sprintf( helpstring, " [file_name]\n Generates %s", modelHelp( which ) ) ; + + options = constructOptions( which, displayopts ) ; + + + /* Hack to save argc and argv so they don't get mangled by getopts */ + /* This is so the command line args can override a reused file header */ + + argc_save = argc ; + argv_save = (char **)malloc( ( argc + 1 ) * sizeof( char *) ) ; + for ( i = 0 ; i < argc ; i++ ) { + argv_save[i] = (char *)malloc( ( strlen( argv[i] ) + 1 ) * sizeof( char ) ) ; + strcpy( argv_save[i], argv[i] ) ; + } + + getopts( options, &argc, &argv ) ; + + if( argc == 0 && isNULL( filestr ) ) { + (void) helpopts( options, programName ) ; + stitch_exit( -1 ) ; + } + + if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 ) + filestr = *argv++ ; + + if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 ) + startstr = *argv++ ; + + if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 ) + lengthstr = *argv++ ; + + if( isNULL( whichstr ) ) + whichstr = which ; + + +/*************************************************************************** +* horrrrrrrrible hack for now to try out -envelope option +***************************************************************************/ + + if( isON( envstr ) ) + if( whichstr[1] == 'b' ) + whichstr[1] = 'e' ; + else { + /* map sai to sie and sas to sse */ + + whichstr[1] = whichstr[2] ; + whichstr[2] = 'e' ; + } + + +/*************************************************************************** +* hack test arguments +***************************************************************************/ +#if 00 + test1 = atof( test1str ) ; + test2 = atof( test2str ) ; + test3 = atof( test3str ) ; + test4 = atof( test4str ) ; +#endif + +/*************************************************************************** +* Open input data file, (use stdin if filename "-" is given). +***************************************************************************/ + + if( strcmp( filestr, "-" ) == 0 ) + inputFilePointer = stdin ; + else + inputFilePointer = fopen( filestr, readBinary ) ; + +/*************************************************************************** +* Position input data file pointer correctly: +* Read any options header at the start of the input file. Set any options. +* Skip to the start of the input data, allowing for any offset (ie startstr). +* Set "framesstr" to the number of frames in the input data file, (here this +* means the number of shorts remaining in the input file). +* Create a source for the input data file. +* Re-set "framesstr" to allow for a given "lengthstr", (ie not the whole file). +***************************************************************************/ + + if( inputFilePointer != (FILE *) 0 ) { + + readopts( options, inputFilePointer ) ; + + headerSize = ftell( inputFilePointer ) ; + + setFrames( fileLength( inputFilePointer ) / sizeof ( short ) - (long) Samples( startstr, Samplerate() ) ) ; + + (void) fseek( inputFilePointer, (long)( headerSize + (long) Samples( startstr, Samplerate() ) * sizeof ( short ) ), 0 ) ; + + source = FileSource( inputFilePointer ) ; + } + + /* If a specific processing amount is specifed (other than "remainder") */ + /* and this amount is less than the remainder of the input file, then */ + /* override the amount of data to process, (in framesstr). */ + + if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) != 0 && + Samples( lengthstr, Samplerate() ) < Frames() ) + setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ; + + +/*************************************************************************** +* Create source with data derived from processing file through model. +* This may involve several stages of callback, and will initialize a chain of +* objects which will ultimately execute the program, (see SinkSource() below). +* If reusestr in "on", the "useprevious" option will use a previously +* generated file, (see checkForFile() routine below). +* If no input data file is found, report error: "could not open file". +* +* The routine ModeledSource() first uses Findstage() to find the appropriate +* place in the stage table called for by the program, (see model.c). +* Then it finds the end of the stage table, and works back up the table to +* the stage called for by the program. Each stage in the table is a process +* on the way to the program as a whole. The order of the stage table sets the +* order of processing. +* Immediately below are the only two calls to routine ModeledSource(). +***************************************************************************/ + + if( isON( reusestr ) ) + source = ModeledSource( source, checkForFile ) ; + else + if( inputFilePointer != (FILE *) 0 ) + source = ModeledSource( source, (Source ( * )()) 0 ) ; + + if( inputFilePointer == (FILE *) 0 ) + stitch_error( "Could not open file \"%s\" for input\n", filestr ) ; + +/*************************************************************************** +* If the "downchannel" option is on, reduce channels by averaging. +* (See DownChannel() routine below). +* Then updateFramebytes sets "framebytesstr" to the total number of bytes +* in each frame, (ie the new width * height). +***************************************************************************/ + + + for( time=0 ; time<OptionInt( downcstr ) ; time++ ) { + source = DownChannel( source, Frameheight() ) ; + setFrameheight( Frameheight() / 2 ) ; + } + updateFramebytes() ; + +#if 0 /* for debugging */ +fprintf( stderr, "%d %d %d %d %ld\n", + Framewidth(), + Frameheight(), + Framebytes(), + Framestep(), + Frames() ) ; +#endif + +/*************************************************************************** +* From here on is concerned with setting up for output, then starting the +* processing, and finally cleaning up. +***************************************************************************/ + +#ifdef X11 +/* First sort out window placement. */ + + if( strcmp( xstr, CenterStr ) == 0 ) + x = -1 ; + else + x = atoi( xstr ) ; + + if( strcmp( ystr, CenterStr ) == 0 ) + y = -1 ; + else + y = atoi( ystr ) ; + + if( isGREYSCALE( viewstr ) ) + pixels = 0 ; + else { + pixels = atoi( penstr ) ; + + if( isON( hiddenstr ) && Frameheight() > 1 ) + + pixels = -abs( pixels ) ; + + /* Convert arguments for line-drawing. See draw.ch */ + drawTilt = atof( tiltstr ) ; + drawDistance = atof( diststr ) ; + drawHeadroom = atof( roomstr ) ; + drawOverlap = atof( overstr ) / 100. ; +#ifdef mips + if( pixels == 0 ) + pixels = 1 ; +#endif + } +#endif /* X11 */ + + /* work out title of output */ + + (void) strcpy( title, filestr ) ; + (void) strcat( title, "." ) ; + (void) strncat( title, whichstr, strlen( "xxx" )+1 ) ; + +#ifdef X11 + + if( strcmp(titlestr,"filename") == 0) /* was: if(isNULL(titlestr)) */ + titlestr = title ; + + /* calculate axis information */ + + if( isEXCITE( viewstr ) ) { + ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; + MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; + } + else if( isWATERFALL( viewstr ) ) { + ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; + TimeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; + } /* landscape ones */ + else if( Framewidth() > 1 ) { + DelayAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; + ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; + } + else { + TimeAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ; + + if( Frameheight() > 1 ) + ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; + else + MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ; + + } + + + /* select outputs... */ + + + /* select sai drawing method */ + + /* Hack so spiral parameters are independent of stage and option order */ + /* (Spiral parameters appear late in options list, so are not known */ + /* when an earlier stage is specified. So don't process unless sai). */ + + if( strncmp(whichstr,"spl",strlen("spl")) == 0 ) { + + frame_drawer = draw_spiral; + + dotthresh_spl = Top() ; + dotsize_spl = OptionInt( penstr ) ; + } + else + frame_drawer = draw_frame; + + /* screen output first */ + /* (set by option: display=on) */ + + if( isON( dispstr ) ) { + + display = newDisplayWindow( titlestr, x, y, atoi( widthstr ), atoi( heightstr ), pixels ) ; + + if( !isGREYSCALE( viewstr ) /* && OptionInt( penstr ) != 0 */ ) { + + if( Top() == Bot() ) + stitch_error( "error: display top and bottom parameters the same value\n" ); + + if( isEXCITE( viewstr ) ) + source = SourceDraw( source, Bot(), Top(), display, Frameheight(), 1, Nwidth(), Frames(), save_frame, frame_drawer ) ; + else if( isWATERFALL( viewstr ) ) + source = SourceDraw( source, Bot(), Top(), display, Frameheight(), Frames(), Nwidth(), 1, save_frame, frame_drawer ) ; + else if( !isON( kludgestr ) ) + source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, frame_drawer ) ; + else { /* speed-up for sai */ + source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, fast_frame ) ; + gen_state = genstate( display, Bot(), Top(), Framewidth(), Frameheight(), Nwidth(), Frames(), pixels ) ; + frame_drawer=fast_frame ; + } + } + else { + if( isON( erasestr ) ) + Clear( display ) ; + + DrawAxes( display ) ; + + if( isON( linstr ) ) + frequency_scale = frequencies ; + else + frequency_scale = (double *) 0 ; + + if( Framewidth() > 1 ) + source = FillDown( display, source, Top(), Bot(), Framewidth(), Frameheight() ) ; + else + source = fillAcross( display, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ; + } + } + + /* postscript output next */ + /* (set by option: postscript=on) */ + + if( isON( psstr ) ) { + + if( isON( psfilestr ) ) + psfilename = AlterSuffix( filestr, POSTSCRIPT_FILE_SUFFIX ) ; + else + psfilename = (char *) 0 ; + +/* the extra argument to newPSWindow. MAA> 27-1-1993. */ + psw = newPSWindow( psfilename, x, y, atoi(widthstr), atoi(heightstr), atoi( penstr ), isON( hiddenstr ) ); + + if( !isGREYSCALE( viewstr ) && OptionInt( penstr ) != 0 ) { + + if( isEXCITE( viewstr ) ) + source = SourceDraw( source, Bot(), Top(), psw, Frameheight(), 1, Nwidth(), Frames(), plot_frame, frame_drawer ) ; + else if( isWATERFALL( viewstr ) ) + source = SourceDraw( source, Bot(), Top(), psw, Frameheight(), Frames(), Nwidth(), 1, plot_frame, frame_drawer ) ; + else + source = SourceDraw( source, Bot(), Top(), psw, Framewidth(), Frameheight(), Nwidth(), Frames(), plot_frame, frame_drawer ) ; + } + else { /* greyscale displays */ + + if( isON( erasestr ) ) + Clear( psw ) ; + + DrawAxes( psw ) ; + + if( isON( linstr ) ) + frequency_scale = frequencies ; + else + frequency_scale = (double *) 0 ; + + if( Framewidth() > 1 ) + source = FillDown( psw, source, Top(), Bot(), Framewidth(), Frameheight() ) ; + else + source = fillAcross( psw, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ; + } + } + + + if( strcmp( typestr, "char" ) == 0 ) { + source = PackShorts( source ) ; + fileFramebytes = Framebytes() / sizeof ( short ) * sizeof ( char ) ; + } + else + +#endif /* X11 */ + + fileFramebytes = Framebytes() ; + + /* output to file */ + + if( !isOFF( outstr ) ) { + + (void) unlink( title ) ; + + if( OptionStringsEqual( outstr, OnOption ) ) + ofp = fopen( title, writeBinary ) ; + else { + if( strcmp( outstr, "stdout" ) == 0 ) + ofp = stdout; + else + ofp = fopen( outstr, writeBinary ) ; + } + + if( ofp == (FILE *) 0 ) + stitch_error( "Unable to open file %s for output\n", title ) ; + else { + if( isON( headstr ) ) + writeopts( options, ofp ) ; + + source = FileTap( source, ofp ) ; + } + } + +#ifdef X11 + + /* output of screen "image" files in display format */ + if( !isOFF( bitmapstr ) ) { + imageFileName = AlterSuffix(filestr, CARTOON_FILE_SUFFIX ) ; + + if( (strcmp( bitmapstr, "stdout" ) == 0 )){ + imageFilePointer = stdout; + writeopts( options, imageFilePointer ) ;} + else + if ( ( imageFilePointer = fopen(imageFileName, writeBinary ) ) == (FILE *) 0) + stitch_error( "Unable to open file %s for image output\n", imageFileName ) ; + else + writeopts( options, imageFilePointer ) ;} + + if (( ofp == stdout ) && ( imageFilePointer == stdout )) + stitch_error( "Both 'output' and 'bitmap' set to stdout.\n", title); + +#endif /* X11 */ + + +/*************************************************************************** +* Execute the program by pulling data from the source. +* This is the only call to routine SinkSource(), which is defined in +* stitch/source.c as sinkSource(). +* (SinkSource is an alias, defined in stitch/source.h, to cast the arguments). +* Routine sinkSource() executes: "(void) Pull( source, fileFramebytes ) ;" +* for "Frames()" times in succession. +* A chain of source objects, linked by callback-function pointers, was setup +* earlier, (see call to ModeledSource() above). +***************************************************************************/ + + + SinkSource( source, fileFramebytes, Frames() ) ; + + +/*************************************************************************** +* Clean up and close +****************************************************************************/ + + CloseSource( source ) ; + + if( ofp != (FILE *) 0 ) + (void) fclose( ofp ) ; + +#ifdef X11 + + if( psw != (WindowObject) 0 ) + Close( psw ) ; + + if( display != (WindowObject) 0 ) { + + /* animate sai's if selected */ + + do + { + for( image=1 ; image <= images ; image++ ) + for( time = OptionInt( animstr ) ; time>0 ; time-- ) + Recall( display, image ) ; + + if( Pause( display ) == 'q' ) + break; + + } while( isON( animstr ) ) ; + + Close( display ) ; + } + +#endif /* X11 */ + + stitch_exit( 0 ) ; +} + +/*************************** End main *************************************/ + +/*************************************************************************** +* checkForFile() +* Create source from file if present, to be used if reusestr in "on". +* This is the "useprevious" option to use previously generated files. +***************************************************************************/ + +Source checkForFile( which ) +char *which ; +{ + static Source noSource = { (struct _source *) 0 } ; + long headerSize, fileFramebytes ; + char file_name[200] ; + FILE *tmp ; + + (void) strcpy( file_name, filestr ) ; + (void) strcat( file_name, "." ) ; + (void) strcat( file_name, which ) ; + + if( ( tmp = fopen( file_name, readBinary ) ) != ( FILE * ) 0 ) { + + inputFilePointer = tmp ; + + (void) fprintf( stderr, "Using existing file \"%s\"\n", file_name ) ; + + readopts( options, inputFilePointer ) ; + + /* the saved command line overrides options from file header */ + + if( isON( reusestr ) ) + cmd_line_opts( options, &argc_save, &argv_save ) ; + + headerSize = ftell( inputFilePointer ) ; + + if( strcmp( typestr, "char" ) == 0 ) + fileFramebytes = Framebytes() / 2 ; + else + fileFramebytes = Framebytes() ; + + /* + If length=remainder then use the whole file. + Otherwise the length of the reused file is that given on the command + line, or the default length (if no length option is given). + */ + + if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) == 0 ) + setFrames( ( fileLength( inputFilePointer ) - headerSize ) / fileFramebytes - (long) Samples( startstr, Samplerate() ) / Framestep() ) ; + else + setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ; + + + (void) fseek( inputFilePointer, headerSize + (long) Samples( startstr, Samplerate() ) / Framestep() * fileFramebytes, 0 ) ; + +#ifndef PC + if( strcmp( typestr, "char" ) == 0 ) + return( CharShortSource( FileSource( inputFilePointer ) ) ) ; + else +#endif + return( FileSource( inputFilePointer ) ) ; + } + else + return( noSource ) ; +} + +/*************************************************************************** +* AlterSuffix(). +* Returns its argument fileName with a newSuffix appended in place of +* any previous suffix it may have had. It should be noted that this +* suffix must include any DOT it wishes to have appended to the name. +***************************************************************************/ + +/* File Name Suffix Conversion Parameters */ + +#define BACKSLASH_CHAR '\\' +#define SLASH_CHARACTER '/' +#define NULL_CHARACTER '\000' +#define DOT_CHARACTER '.' + +char *AlterSuffix(fileName, newSuffix) + char *fileName, *newSuffix; +{ + char *temp, *temp2, *lastPart; +#if defined( PC ) + int i; +#endif + + temp = stitch_malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1), "AlterSuffix" ); + + temp = strcpy(temp, fileName); + +#if defined(PC) + /* Change all backslashes to forward slashes */ + for (i = 0; temp[i] != NULL_CHARACTER; i++) + if (temp[i] == BACKSLASH_CHAR) + temp[i] = SLASH_CHARACTER; +#endif + + if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL) + lastPart = temp; + else + lastPart++; /* Skip over the actual "/" */ + + /* lastPart points to the tail name of the path */ + + if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL) + temp = strcat(temp, newSuffix); + else + temp2 = strcpy(temp2, newSuffix); + + return (temp); +} + +#ifdef X11 + +/*************************************************************************** +* Interceptions for various combinations of drawing. +* An "interception function" is a function inserted into a chain a functions +* linked by function pointers. The inserted function "intercepts" the +* processing, to perform some transformation. +****************************************************************************/ + +/* intercept draw to store images for animation */ + +void save_frame( state, frame, first ) +struct _draw_state *state ; +short *frame ; +int first ; +{ + if( first ) { + if( isON( erasestr ) ) + Clear( state->window ) ; + + if( frame_drawer != (void (*)()) draw_spiral && state->framenumber == 1 ) + DrawAxes( state->window ) ; + } + + frame_drawer( state, frame ) ; + + if( isON( animstr ) && isOFF( kludgestr ) ) + if( Store( state->window ) ) + ++images ; + + if( isON( bitmapstr ) ) + Write( state->window, imageFilePointer ) ; + + return ; +} + +/* hacky but effective faster frame drawing routine - for sai only! */ + +void fast_frame( state, frame, first ) +struct _draw_state *state ; +short *frame ; +int first ; +{ + if( isON( animstr ) || images == 0 ) + if( Store( state->window ) ) + ++images ; + + /* generate image in current cleared image */ + + generate( gen_state, frame ) ; + + /* then recal the window using the modified image */ + + Recall( state->window, images ); + + return ; +} + +/* intercept plot to check if page should be output for printing */ + +static int plot_wanted( state ) +struct _draw_state *state ; +{ +#if !defined(PC) + if( display != ( WindowObject ) 0 && state->framewidth > 1 && state->frames > 1 ) { + (void) fprintf(stderr, "Hit \"y\" to include this image in the PostScript file: "); + + switch ( Pause( display ) ) { + + case 'y' : case 'Y' : + case 'p' : case 'P' : + return 1 ; + + default : + return 0 ; + } + } +#endif + return 1 ; +} + +void plot_frame( state, frame, first ) +struct _draw_state *state ; +short *frame ; +int first ; +{ + int centering = state->window->entries->x( state->window ) < 0 && + state->window->entries->y( state->window ) < 0 ; + + if( isOFF( erasestr ) || state->framewidth == 1 || plot_wanted( state ) ) { + + if( first && ( state->framenumber == 1 || isON( erasestr ) ) ) { +/* *** if( centering ) *** removed the conditional. M.Akeroyd. 22-1-1993.*/ + Clear( state->window ) ; + + if( frame_drawer != (void (*)()) draw_spiral ) + DrawAxes( state->window ) ; + } + + frame_drawer( state, frame ) ; + } + + return ; +} + +#endif /* X11 */ + +/*************************************************************************** +* downchannel: average across channels for output (with special sai version) +***************************************************************************/ + +struct _down_channel_state { + struct _fillable_source parent ; + int channels ; + Source input ; +} ; + + +static Pointer down_channel_callback( state, bytes, buffer ) +struct _down_channel_state *state ; +ByteCount *bytes ; +short *buffer ; +{ + register int last = *bytes == 0 ; + register int chan, outchans = state->channels >> 1 ; + long frame, frames = ToPoints( short, *bytes ) / outchans ; + register short *iptr = PullItems( state->input, frames * state->channels, short ) ; + register short *bptr = buffer ; + + for( frame=0 ; frame<frames ; frame++ ) { + for( chan=0 ; chan<outchans ; chan++ ) + *bptr++ = ( *iptr++ + *iptr++ ) / 2 ; + + if( ( outchans << 1 ) != state->channels ) + iptr++ ; + } + + if( !last ) + return ( (Pointer) buffer ) ; + else + return ( DeleteFillableSource( state ) ) ; +} + +static Pointer down_channel_callback_sai( state, bytes, buffer ) +struct _down_channel_state *state ; +ByteCount *bytes ; +short *buffer ; +{ + register int last = *bytes == 0 ; + register int chan, outchans = state->channels >> 1 ; + long frame, frames = ToPoints( short, *bytes ) / outchans ; + register short *iptr = PullItems( state->input, frames * state->channels, short ) ; + register short *bptr = buffer ; + register short *iptr2 ; + + iptr2 = iptr + frames ; + for( chan=0 ; chan<outchans ; chan++ ) { + for( frame=0 ; frame<frames ; frame++ ) + *bptr++ = ( *iptr++ + *iptr2++ ) / 2 ; + } + + if( !last ) + return ( (Pointer) buffer ) ; + else + return ( DeleteFillableSource( state ) ) ; +} + + +Source DownChannel( source, channels ) +Source source ; +{ + DeclareNew( struct _down_channel_state *, state ) ; + + state->channels = channels ; + state->input = source ; + + + /* Hack for special-case downchannel routine to handle format of sai and spl frames (mha: 22/6/93) */ + + if( strncmp(whichstr,"sai",strlen("sai")) == 0 || + strncmp(whichstr,"spl",strlen("spl")) == 0 ) + + return ( SetFillableSource( state, down_channel_callback_sai, "down channeling sai frames" ) ) ; + + return ( SetFillableSource( state, down_channel_callback, "down channeling" ) ) ; +} + + +#ifdef X11 + +/*************************************************************************** +* Pack model output onto a single byte if required, +* using greyscale Top() from display. +***************************************************************************/ + +typedef struct { struct _fillable_source parent ; Source input ; } *PackSource ; + +static Pointer pack_callback( state, bytes, buffer ) +PackSource state ; +ByteCount *bytes ; +Pointer buffer ; +{ + register int last = *bytes == 0 ; + register short *iptr = PullShorts( state->input, *bytes ) ; + register Pointer optr = buffer ; + register Pointer eptr = buffer + *bytes ; + register int bytemax = atoi( bmaxstr ) ; + register int max = Top() ; + register int min = Bot() ; + + while( optr < eptr ) + if( *iptr > max ) { + *optr++ = bytemax ; + iptr++ ; + } + else if( *iptr < min ) { + *optr++ = 0 ; + iptr++ ; + } + else + *optr++ = ( ( ( *iptr++ - min ) * bytemax + ( bytemax >> 1 ) ) / ( max - min ) ) & 0xff ; + + if( !last ) + return ( buffer ) ; + else + return ( DeleteFillableSource( state ) ) ; +} + + +Source PackShorts( input ) +Source input ; +{ + DeclareNew( PackSource, source ) ; + + source->input = input ; + + return ( SetFillableSource( source, pack_callback, "gen.c packing" ) ) ; +} + +#endif /* X11 */ + +/***************************************************************************/ + +#ifdef PC +static lowerArgs( argv, argc ) +char **argv ; +int argc ; +{ + register char *ptr ; + register int arg ; + + for( arg=0 ; arg<=argc ; arg++ ) + for( ptr=argv[arg] ; *ptr != '\000' ; ptr++ ) + if( isupper( *ptr ) ) + *ptr = tolower( (int) *ptr ) ; + return ; +} +#endif + + +/*************************************************************************** +* Set the value of versionstr to the model version number and current time. +* The version number is the sccs <release-number>.<level-number> of the file +* version.c. The current time is returned by ctime(time(0)). +* This routine initializes the default version-string (headerstr), which is +* later copied into the version-string (versionstr) during getopts(). +* In this way, the version-string is available for output at the head of +* the help and the options (rc) files, and also output as part of the header, +* (when output=on). +* Note, the versionstr has to be quoted, otherwise the routine +* processOptionFile in options.c will report an error (Detected Trailing...) +* when it finds blanks within a line. This happens when trying to read an +* options file, for example when reviewing. The addition of quotes enables +* a line containing blanks to be read complete by the subroutine getName. +***************************************************************************/ + +#include "version.c" + +getversion( name ) +char *name ; +{ + char releasestr[8] ; + char levelstr[8] ; + char timestr[32] ; + char *namestr ; + long int timeval ; + + sprintf(releasestr, "%d", atoi( version_Id ) ) ; + sprintf(levelstr, "%d", atoi( version_Id + strlen(releasestr) + 1 ) ) ; + + if ( ( namestr = strrchr( name, '/' ) ) == (char *)0 ) namestr = name ; + else namestr++ ; + +#if defined( PC ) || defined( THINK_C ) + sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s]\"", releasestr, levelstr, namestr ) ; +#else + timeval = time(0); + sprintf(timestr,"%s", ctime(&timeval) ) ; + timestr[strlen(timestr) - 1] = '\0'; /* remove newline */ + sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s] %s\"", releasestr, levelstr, namestr, timestr ) ; +#endif + +}