Metropoli BBS
VIEWER: settings.c MODE: TEXT (ASCII)
/***************************************************************************
 *		  Copyright (C) 1994  Charles P. Peterson                  *
 *	     4007 Enchanted Sun, San Antonio, Texas 78244-1254             *
 *              Email: Charles_P_Peterson@fcircus.sat.tx.us                *
 *                                                                         *
 *		  This is free software with NO WARRANTY.                  *
 *	      See gfft.c, or run program itself, for details.              *
 *		      Support is available for a fee.                      *
 ***************************************************************************
 *
 * Program:     gfft--General FFT analysis
 * File:        settings.c
 * Purpose:     set values, names, and operation types
 * Author:      Charles Peterson (CPP)
 * History:     31-May-1993 CPP; Created.
 *              9-Aug-94 CPP (1.10); Hidden3D option
 *              19-Jan-95 CPP (1.21); Topaz command
 *              10-Feb-95 CPP (1.39; save settings or parameters
 *              14-Feb-95 CPP (1.42); PlotCommands
 */

#include <stdio.h>     /* printf */
#include <string.h>    /* strtok, strlen */
#include <stdlib.h>    /* strtoul */
#include <errno.h>     /* errno */

#include "gfft.h"

#define DEFINE_HERE
#include "settings.h"
#undef DEFINE_HERE

extern Name_Info_St Gfft_Command[];  /* GFFT commands */

static char *set_ulong (char *arguments, unsigned long *longp, 
			   int gt_0_req, int arg_req);

static char *set_double (char *arguments, double *doublep, 
			   int gt_0_req, int arg_req);

static char *get_filename (char *arguments, char **filename_pp);

static char *add_calibration (char *arguments, BOOLEAN db_scale);

char *set (char *arguments)
{
/*
 * Dummy command which invokes its arguments as a command string
 */
    if (arguments && arguments != NullString)
    {
	invoke_method (arguments, Gfft_Command);
    }
    return arguments;
}

/*
 * Functions to set various parameters
 */

char *set_time_offset (char *arguments)
{
    char *more_arguments;
    ULONG time_offset;

    TimeOffset = INVALID_SET;  /* unless this succeeds */
    more_arguments = set_ulong (arguments, &time_offset, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	TimeOffset = NOT_SET;
    }
    else
    {
	Time3D = TRUE;
	if (time_offset > 0 && time_offset < LONG_MAX)
	{
	    TimeOffset = (long) time_offset;
	}
	else
	{
	    command_error_message (BAD_ARGUMENT, more_arguments-1);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
    }
    return more_arguments;
}

char *set_time_segments (char *arguments)
{
    char *more_arguments;
    ULONG time_segments;

    TimeSegments = INVALID_SET;  /* unless this succeeds */
    more_arguments = set_ulong (arguments, &time_segments, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	TimeSegments = NOT_SET;
    }
    else
    {
	Time3D = TRUE;
	TimeSegSize = NOT_SET;
	if (time_segments > 0 && time_segments < LONG_MAX)
	{
	    TimeSegments = (long) time_segments;
	}
	else
	{
	    command_error_message (BAD_ARGUMENT, more_arguments-1);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
    }
    return more_arguments;
}

char *set_key (char *arguments)
{
    char *more_arguments;

    more_arguments = set_ulong (arguments, &Key, FALSE, FALSE);
    return more_arguments;
}

char *set_time_seg_size (char *arguments)
{
    char *more_arguments;
    ULONG time_seg_size;

    TimeSegSize = INVALID_SET;  /* unless this succeeds */
    more_arguments = set_ulong (arguments, &time_seg_size, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	TimeSegSize = NOT_SET;
    }
    else
    {
	Time3D = TRUE;
	TimeSegments = NOT_SET;
	if (time_seg_size > 0 && time_seg_size < LONG_MAX)
	{
	    TimeSegSize = (long) time_seg_size;
	}
	else
	{
	    command_error_message (BAD_ARGUMENT, more_arguments-1);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
    }
    return more_arguments;
}

char *set_smoothing_segments (char *arguments)
{
    char *more_arguments;
    ULONG smoothing_segs;

    SmoothingSegments = INVALID_SMOOTHING;  /* unless this succeeds */
    more_arguments = set_ulong (arguments, &smoothing_segs, TRUE, FALSE);
    if (more_arguments == NullString)
    {
	SmoothingSegments = NO_SMOOTHING;
    }
    else
    {
	if (smoothing_segs <= LONG_MAX)
	{
	    SmoothingSegments = (long) smoothing_segs;
	}
	else
	{
	    command_error_message (BAD_ARGUMENT, more_arguments-1);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
    }
    return more_arguments;
}

char *set_time_3d (char *arguments)
{
    Time3D = TRUE;
    return arguments;
}

char *set_no_time_3d (char *arguments)
{
    Time3D = FALSE;
    return arguments;
}

char *set_hidden_3d (char *arguments)
{
    Hidden3D = TRUE;
    return arguments;
}

char *set_no_hidden_3d (char *arguments)
{
    Hidden3D = FALSE;
    return arguments;
}

char *set_signed (char *arguments)
{
    InputFormat.zero = 0;
    return arguments;
}

char *set_unsigned (char *arguments)
{
	int sample_width = (InputFormat.bits > 8) ? 16 : 8;
	InputFormat.zero = ((unsigned long) 0xffffffff >> 
			    (33 - sample_width)) + (unsigned long) 1;
/*
 * This is re-done at time of 'ok' command to be sure bits spec is final
 */
    return arguments;
}

char *set_terminal (char *arguments)
{
    char *more_arguments;
    char *terminal; 

    if (Terminal && Terminal != NullString)
    {
	gfree (Terminal);
	Terminal = NULL;
    }
    more_arguments = get_filename (arguments, &terminal);
    if (terminal == NullString || strlen (terminal) == 0)
    {
	Terminal = NULL;
    }
    else
    {
	Terminal = terminal;
    }
    return more_arguments;
}


char *set_plot_output (char *arguments)
{
    char *more_arguments;
    char *plot_output; 

    if (PlotOutput && PlotOutput != NullString)
    {
	gfree (PlotOutput);
	PlotOutput = NULL;
    }
    more_arguments = get_filename (arguments, &plot_output);
    if (plot_output == NullString || strlen (plot_output) == 0)
    {
	PlotOutput = NULL;
    }
    else
    {
	PlotOutput = plot_output;
    }
    return more_arguments;
}


char *set_save_memory (char *arguments)
{
    SaveMemory = TRUE;
    return arguments;
}

char *set_no_save_memory (char *arguments)
{
    SaveMemory = FALSE;
    return arguments;
}

char *set_psdensity (char *arguments)
{
    PSDensity = TRUE;
    return arguments;
}

char *set_no_psdensity (char *arguments)
{
    PSDensity = FALSE;
    return arguments;
}

char *set_squared_smoothing (char *arguments)
{
    SquaredSmoothing = TRUE;
    return arguments;
}

char *set_no_squared_smoothing (char *arguments)
{
    SquaredSmoothing = FALSE;
    return arguments;
}

char *set_combine_plots (char *arguments)
{
    extern int Old_File_Count;

    if (!CombinePlots)
    {
	CombinePlots = TRUE;
	Old_File_Count = (Old_File_Count > 0) ? 1 : 0;
    }
    return arguments;
}

char *set_no_combine_plots (char *arguments)
{
    CombinePlots = FALSE;
    Old_File_Count = 0;
    return arguments;
}

char *cut_combined_plot (char *arguments)
{
    if (Old_File_Count > 0) Old_File_Count--;
    return arguments;
}

char *set_db (char *arguments)
{
    Db = TRUE;
    return arguments;
}

char *set_header (char *arguments)
{
    Header = TRUE;
    return arguments;
}

char *set_no_header (char *arguments)
{
    Header = FALSE;
    return arguments;
}

char *set_logx (char *arguments)
{
    LogX = TRUE;
    return arguments;
}

char *set_logy (char *arguments)
{
    LogY = TRUE;
    return arguments;
}

char *set_no_logx (char *arguments)
{
    LogX = FALSE;
    return arguments;
}

char *set_no_logy (char *arguments)
{
    LogY = FALSE;
    return arguments;
}

char *set_no_db (char *arguments)
{
    Db = FALSE;
    return arguments;
}

char *set_time_overlap (char *arguments)
{
    char *beyond_argument;

    TimeOverlap = INVALID_SET;
    beyond_argument = set_double (arguments, &TimeOverlap, FALSE, FALSE);
    if (beyond_argument == NullString)
    {
	TimeOverlap = DEFAULT_TIME_OVERLAP;
    }
    else 
    {
	Time3D = TRUE;
	TimeOffset = NOT_SET;
	if (TimeOverlap >= 1.0 || TimeOverlap < 0.0)
	{
	    TimeOverlap = INVALID_SET;
	    command_error_message (BAD_ARGUMENT, beyond_argument-1);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
    }
    return beyond_argument;
}

char *set_no_quantization (char *arguments)
{
    Quantization = MIN_QUANTIZATION;
    return arguments;
}

char *set_quantization (char *arguments)
{
    double quantization = 0.0;
    char *beyond_argument;

    Quantization = BAD_QUANTIZATION;
    beyond_argument = set_double (arguments, &quantization, FALSE, FALSE);
    if (beyond_argument == NullString || quantization == 0.0)
    {
	Quantization = MIN_QUANTIZATION;  /* Default value if no argument */
    }
    else if (quantization < 0.0)
    {
	command_error_message (BAD_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    else
    {
	Quantization = quantization;
    }
    return beyond_argument;
}

char *set_multiply (char *arguments)
{
    char *beyond_argument;

    beyond_argument = set_double (arguments, &Multiply, FALSE, FALSE);
    if (beyond_argument == NullString)
    {
	Multiply = 1.0L;  /* Default value if no argument */
    }
    return beyond_argument;
}

char *set_no_one_shot_only (char *arguments)
{
    OneShotOnly = FALSE;
    return arguments;
}

char *set_topaz (char *arguments)
{
    Topaz = TRUE;
    return arguments;
}


char *set_no_repeat_only (char *arguments)
{
    RepeatOnly = FALSE;
    return arguments;
}

char *set_bits (char *arguments)
{
    char *more_arguments;
    ULONG bits;

    more_arguments = set_ulong (arguments, &bits, TRUE, FALSE);
    if (more_arguments == NullString)
    {
	bits = DEFAULT_INPUT_BITS;
    }
    else if (1 > bits || bits > 16)
    {
	command_error_message (BAD_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    else
    {
	InputFormat.bits = bits;
    }
    return more_arguments;
}

char *set_octave (char *arguments)
{
    char *more_arguments;

    more_arguments = set_ulong (arguments, &Octave, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	Octave = 1L;
    }
    return more_arguments;
}

char *set_one_shot_only (char *arguments)
{
    OneShotOnly = TRUE;
    RepeatOnly = FALSE;
    return arguments;
}

char *set_repeat_only (char *arguments)
{
    RepeatOnly = TRUE;
    OneShotOnly = FALSE;
    return arguments;
}

char *set_ignore_format (char *arguments)
{
    IgnoreFormat = TRUE;
    return arguments;
}

char *set_no_ignore_format (char *arguments)
{
    IgnoreFormat = FALSE;
    return arguments;
}

char *set_pink (char *arguments)
{
    Pink = TRUE;
    return arguments;
}

char *set_no_pink (char *arguments)
{
    Pink = FALSE;
    return arguments;
}

char *set_parseval (char *arguments)
{
    Parseval = TRUE;
    return arguments;
}

char *set_no_parseval (char *arguments)
{
    Parseval = FALSE;
    return arguments;
}

char *set_overlap (char *arguments)
{
    Overlap = TRUE;
    return arguments;
}

char *set_no_overlap (char *arguments)
{
    Overlap = FALSE;
    return arguments;
}

char *set_high_frequency (char *arguments)
{
    char *more_arguments;

    more_arguments = set_double (arguments, &HighFrequency, FALSE, FALSE);
    if (more_arguments == NullString)
    {
        HighFrequency = HIGHEST_FREQUENCY;   /* No arg, return to default */
    }
    return more_arguments;
}

char *set_low_frequency (char *arguments)
{
    char *more_arguments;

    more_arguments = set_double (arguments, &LowFrequency, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	LowFrequency = LOWEST_FREQUENCY;   /* No arg, return to default */
    }
    return more_arguments;
}

char *set_low_y (char *arguments)
{
    char *more_arguments;

    more_arguments = set_double (arguments, &LowY, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	LowY = LOWEST_Y;   /* No arg, return to default */
    }
    return more_arguments;
}

char *set_high_y (char *arguments)
{
    char *more_arguments;

    more_arguments = set_double (arguments, &HighY, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	HighY = HIGHEST_Y;   /* No arg, return to default */
    }
    return more_arguments;
}

char *set_channel (char *arguments)
{
    char *more_arguments;

    Channel = 0L;    /* Purposely set to invalid value here */
    more_arguments = set_ulong (arguments, &Channel, TRUE, FALSE);
    if (more_arguments == NullString)
    {
	Channel = 1L;   /* Return to default if no argument */
    }
    if (Channel > FileChannels || Channel < 1)
    {
	error_message (SPEC_CHANNEL_UNAVAIL);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    return more_arguments;
}

char *set_start_byte (char *arguments)
{
    char *more_arguments;

    more_arguments = set_ulong (arguments, &StartByte, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	StartByte = 0;   /* Return to default if no argument */
    }
    return more_arguments;
}

char *set_start_frame (char *arguments)
{
    char *more_arguments;

    more_arguments = set_ulong (arguments, &StartFrame, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	StartFrame = 0;   /* Return to default if no argument */
    }
    return more_arguments;
}

char *set_frames (char *arguments)
{
    char *more_arguments;

    more_arguments = set_ulong (arguments, &Frames, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	Frames = ULONG_MAX;   /* Return to default if no argument */
    }
    return more_arguments;
}

char *set_pad (char *arguments)
{
    Pad = TRUE;
    return arguments;
}

char *set_no_pad (char *arguments)
{
    Pad = FALSE;
    return arguments;
}

char *set_no_numerical (char *arguments)
{
    Numerical = FALSE;
    return arguments;
}

char *set_numerical (char *arguments)
{
#ifdef NUMERICAL_RECIPES_AVAILABLE
    Numerical = TRUE;
#else
    error_message (NO_NUMERICAL);
    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
#endif
    return arguments;
}


#define GNUPLOT 1

static char *set_plot_gnuplot (char *arguments)
{
    Plot = GNUPLOT_PLOT;
    return arguments;
}

static Name_Info_St plotter_names[] = {
  {"GNUPLOT","G", set_plot_gnuplot},
  {"","", default_argument},
};


char *set_plot (char *arguments)
{
    char *arg;

    arg = strtok (arguments, " ");
    if (!arg) /* No argument present */
    {
	Plot = ANY_PLOT;  /* use the default plotter */
    }
    else
    {
	invoke_method (arg, plotter_names);
    }
    return arguments;
}

char *set_no_plot (char *arguments)
{
    Plot = NO_PLOT;
    return arguments;
}


#define ASCII 1
#define BINARY 2

static char *set_output_format_binary (char *arguments)
{
    OutputFormat.binary = TRUE;
    return arguments;
}

static char *set_output_format_ascii (char *arguments)
{
    OutputFormat.binary = FALSE;
    return arguments;
}

static Name_Info_St output_format_names[] = {
  {"ASCII","A", set_output_format_ascii},
  {"BINARY","B", set_output_format_binary},
  {"","", default_argument},
};

char *set_output (char *arguments)
{
    char *arg;

    arg = strtok (arguments, " ");
    if (!arg) /* No argument present */
    {
	command_error_message (MISSING_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    invoke_method (arg, output_format_names);
    return arguments;
}

char *set_amplitude (char *arguments)
{
    Amplitude = TRUE;
    Power = FALSE;
    return arguments;
}

char *set_power (char *arguments)
{
    Power = TRUE;
    Amplitude = FALSE;
    return arguments;
}

char *set_fft (char *arguments)
{
    Power = FALSE;
    Amplitude = FALSE;
    return arguments;
}

char *set_mean (char *arguments)
{
    Mean = TRUE;
    return arguments;
}

char *set_sum (char *arguments)
{
    Mean = FALSE;
    return arguments;
}

char *set_hann (char *arguments)
{
    WindowType = HANN_WINDOW;
    return arguments;
}

char *set_hamming (char *arguments)
{
    WindowType = HAMMING_WINDOW;
    return arguments;
}

char *set_parzen (char *arguments)
{
    WindowType = PARZEN_WINDOW;
    return arguments;
}

char *set_rectangle (char *arguments)
{
    WindowType = RECTANGLE_WINDOW;
    return arguments;
}

char *set_triangle (char *arguments)
{
    WindowType = TRIANGLE_WINDOW;
    return arguments;
}

char *set_blackman_harris_74db (char *arguments)
{
    WindowType = BLACKMAN_HARRIS_74DB_WINDOW;
    return arguments;
}

char *set_blackman_harris_92db (char *arguments)
{
    WindowType = BLACKMAN_HARRIS_92DB_WINDOW;
    return arguments;
}

char *set_welch (char *arguments)
{
    WindowType = WELCH_WINDOW;
    return arguments;
}

char *set_rotation_x (char *arguments)
{
    char *more_arguments;
    double rot_x;

    RotX = INVALID_ROTATION;
    more_arguments = set_double (arguments, &rot_x, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	RotX = DEF_ROT_X;
    }
    else if (0. <= rot_x && rot_x <= 180.)
    {
	RotX = rot_x;
    }
    else
    {
	command_error_message (BAD_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    return more_arguments;
}

char *set_rotation_z (char *arguments)
{
    char *more_arguments;
    double rot_z;

    RotZ = INVALID_ROTATION;
    more_arguments = set_double (arguments, &rot_z, FALSE, FALSE);
    if (more_arguments == NullString)
    {
	RotZ = DEF_ROT_Z;
    }
    else if (0. <= rot_z && rot_z <= 360.)
    {
	RotZ = rot_z;
    }
    else
    {
	command_error_message (BAD_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    return more_arguments;
}

char *set_rate (char *arguments)
{
    char *more_arguments;

    Rate = INVALID_RATE;   /* Preset to <invalid> rate */
    more_arguments = set_double (arguments, &Rate, TRUE, FALSE);
    if (more_arguments == NullString)
    {
	Rate = AUTO_RATE;   /* Set to <auto/default> rate */
    }
    return more_arguments;
}

char *set_interleave (char *arguments)
{
    char *end_argument;
    ULONG interleave = 0;

    Interleave = INVALID_INTERLEAVE;   /* Force flagged value on error */
    end_argument = set_ulong (arguments, &interleave, TRUE, TRUE);
    if (interleave < 2)
    {
	command_error_message (BAD_ARGUMENT, end_argument-1);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    else
    {
	Interleave = interleave;
    }
    return end_argument;
}

char *set_no_interleave (char *arguments)
{
    Interleave = 1;
    return arguments;
}

char *set_bins (char *arguments)
{
    unsigned long bins = 1;
    unsigned long okbins = 1;
    char *new_arguments;

    NumberBins = INVALID_BINS;   /* Preset invalid value in case of error */
    new_arguments = set_ulong (arguments, &bins, FALSE, FALSE);
    if (new_arguments != NullString)
    {
	if (bins == 0)
	{
	    NumberBins = 0;
	    return new_arguments;
	}
	okbins = get_pos_power_2 (bins);
	if (okbins > LONG_MAX)
	{
	    okbins = get_pos_power_2 (LONG_MAX / 2L);
	}
	NumberBins = (long) okbins;
	if (NumberBins != bins)
	{
	    bins_s_message ();
	}
    }
    else
    {
	NumberBins = MAX_BINS;  /* Default...based on data count of file */
    }
    return new_arguments;
}


unsigned long get_pos_power_2 (unsigned long i)
{
    unsigned long j = 1;                /* minimum useful value */
    unsigned long max = ULONG_MAX / 2;  /* max value we can safely handle */

    for (j = 1; j < max; j *= 2)
    {
	if (j >= i) break;
    }
    return j;
}

char *set_no_calibrations (char *arguments)
{
    calibration_list__cancel (&CalibrationList);
    CalibrationList = NULL;
    return arguments;
}

char *set_db_calibration (char *arguments)
{
    arguments = add_calibration (arguments, TRUE);
    return arguments;
}

char *set_calibration (char *arguments)
{
    arguments = add_calibration (arguments, FALSE);
    return arguments;
}

static char *add_calibration (char *arguments, BOOLEAN db_scale)
{
    char *more_arguments;
    FILE *cal_file;
    char *cal_name;

    more_arguments = get_filename (arguments, &cal_name);
    if (cal_name == NullString)
    {
	command_error_message (MISSING_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);   /* longjmp outa here */
    }
    if (!(cal_file = fopen (cal_name,"r")))
    {
	error_message (CANT_OPEN_INPUT_FILE);
	RAISE_ERROR (NOTHING_SPECIAL);   /* longjmp outa here */
    }
    calibration_list__add (&CalibrationList, cal_name, cal_file, db_scale);
    return more_arguments;
}


char *load_settings (char *arguments)
{
    char *more_arguments;
    char *filename;
    FILE *fptr;

    more_arguments = get_filename (arguments, &filename);

    if (filename == NullString)
    {
	command_error_message (MISSING_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }

    if (!(fptr = fopen (filename,"r")))
    {
	error_message (CANT_OPEN_INPUT_FILE);
	RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */
    }
    CATCH_ERROR
    {
	execute_file_commands (fptr);
    }
    END_CATCH_ERROR;

    fclose (fptr);

    return more_arguments;
}


char *set_read (char *arguments)
{
    char *more_arguments;

    if (ReadName && ReadName != NullString)
    {
	gfree (ReadName);
	ReadName = NullString;
    }
    if (ReadPtr != NULL && ReadPtr != stdin)
    {
	fclose (ReadPtr);
    }
    if (Save_Data)
    {
	gfree (Save_Data);
	Save_Data = NULL;
    }
    more_arguments = get_filename (arguments, &ReadName);
    if (ReadName == NullString)
    {
	reset_format ();
	ReadPtr = NULL;
	ReadName = NULL;
	return more_arguments;
    }
    if (strlen (ReadName) == 4 && !strcmp (ReadName,"con:"))
    {
	reset_format ();
	ReadPtr = stdin;
	return more_arguments;
    }
    if (!(ReadPtr = fopen (ReadName,"r")))
    {
	error_message (CANT_OPEN_INPUT_FILE);
	reset_format ();
	RAISE_ERROR (NOTHING_SPECIAL); /* longjmp outa here! */
    }
    else
    {
	read_format ();
    }
    return more_arguments;
}

char *set_append (char *arguments)
{
    char *more_arguments;

    Appending = FALSE;
    if (WriteName && WriteName != NullString)
    {
/*	gfree (WriteName);      aliased name!  unsafe to free!  */
	WriteName = NullString;
    }
    if (WritePtr != NULL && WritePtr != stdout)
    {
	fclose (WritePtr);
    }
    WritePtr = NULL;
    more_arguments = get_filename (arguments, &WriteName);
    if (WriteName == NullString)
    {
	Appending = TRUE;
	WriteName = NULL;
	return more_arguments;
    }
    WritePtr = fopen (WriteName,"a");
    if (!WritePtr)
    {
	error_message (CANT_CREATE_OUTPUT_FILE);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    Appending = TRUE;
    return more_arguments;
}

char *set_write (char *arguments)
{
/*
 * The following is intended to maximize portability
 * by using (ultimately) only ANSI C functions and notions
 *
 * Note: If the first characters match the TEMP_DATAFILE_NAME, the
 *   previous version will be overwritten with impunity, otherwise:
 * if a file exists with the same name, it will be renamed to backup.
 * Only one level of backup files is created.
 * It will fail if filesystem does not allow a one character suffix.
 * If the backup fails, file is not opened for output.
 */
    char *more_arguments;
    FILE *temp_ptr;

    Appending = FALSE;
    if (WriteName && WriteName != NullString)
    {
/*	gfree (WriteName);      aliased name!  unsafe to free!  */
	WriteName = NullString;
    }
    if (WritePtr != NULL && WritePtr != stdout)
    {
	fclose (WritePtr);
    }
    WritePtr = NULL;
    more_arguments = get_filename (arguments, &WriteName);
    if (WriteName == NullString)
    {
	WriteName = NULL;
	return more_arguments;
    }
    if (strlen (WriteName) == 4 && !strcmp (WriteName,"con:"))
    {
	WritePtr = stdout;
	return more_arguments;
    }
    if (!is_temp_file (WriteName))
    {
	if (temp_ptr = fopen (WriteName,"r"))
	{
	    int oldlen;
	    char *newname;
	    int old_backup_deleted = FALSE;
	    
	    fclose (temp_ptr);
	    oldlen = strlen (WriteName);
	    newname = gmalloc (oldlen + 2, NOTHING_SPECIAL);
	    strcpy (newname, WriteName);
	    newname[oldlen] = BACKUP_FILE_CHARACTER;
	    newname[oldlen + 1] = '\0';
	    if (temp_ptr = fopen (newname,"r"))
	    {
		old_backup_deleted = TRUE;
		fclose (temp_ptr);
		remove (newname);
	    }
	    if (rename (WriteName, newname))
	    {
		error_message (OUTPUT_BACKUP_FAILURE);
		RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	    }
	    else if (old_backup_deleted)
	    {
		error_message (BACKUP_OVERWRITTEN);  /* Warning only. */
	    }
	    else
	    {
		error_message (BACKUP_CREATED);  /* Warning only. */
	    }
	    gfree (newname);
	}
    }
    WritePtr = fopen (WriteName,"w");
    if (!WritePtr)
    {
	error_message (CANT_CREATE_OUTPUT_FILE);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    return more_arguments;
}

char *clear_plot_commands (char *arguments)
{
    PlotCommands = NULL;
    return arguments;
}

char *add_plot_command (char *arguments)
{
    struct list_st **plot_basep = &PlotCommands;
    char *command;

    while (*plot_basep != NULL)
    {
	plot_basep = &((*plot_basep)->next);
    }
    *plot_basep = (struct list_st *) gcalloc (1, sizeof (struct list_st), 
			  NOTHING_SPECIAL);
    command = (char *) gmalloc (1+strlen(arguments), NOTHING_SPECIAL);
    strcpy (command, arguments);
    (*plot_basep)->node = (void *) command;
    (*plot_basep)->next = NULL;
    return NullString;
}

void write_plot_commands (FILE *fp, char *cstr, char *name,
		      struct list_st *plot_commands)
{
    while (plot_commands)
    {
	/* fortunately, GNUPLOT ignores leading whitespace */
	fprintf (fp, "%s%s %s\n", cstr, name, 
		(char *) plot_commands->node);
	plot_commands = plot_commands->next;
    }
}





/* Utility functions *****************************************************/

/*
 * Set an unsigned long value
 * decimal, octal, or hex accepted
 * handle error, incl. termination by other than NULL, space, or newline
 * on error, longjmp (to command loop)
 * a flag determines if value greater than 0 is required
 * a flag determines if argument is mandatory (then longjmp if not present)
 * if argument not mandatory, return NullString if no arg found, 
 *  otherwise, return string pointer to first char past end of filename
 *    (this may be simply a pointer to a '\0' byte)
 * value is only set if found and successful
 */
static char *set_ulong (char *arguments, unsigned long *valuep, 
			   int gt_0_req, int arg_req)
{
    char *arg;
    char *beyondpointer = NULL;
    unsigned long newvalue;

    arg = strtok (arguments, " ");
    if (!arg) /* No argument present */
    {
	if (arg_req)
	{
	    command_error_message (MISSING_ARGUMENT, arguments);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
	return NullString;
    }
    errno = 0;
    newvalue = strtoul (arg, &beyondpointer, 0);
    if (errno || (newvalue == 0 && gt_0_req))
    {
	command_error_message (BAD_ARGUMENT, arg);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    if (*beyondpointer != ' ' && *beyondpointer != '\0' && 
	*beyondpointer != '\n')    /* illegal character in number */
    {
	command_error_message (BAD_ARGUMENT, beyondpointer);
        RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    *valuep = newvalue;
    return beyondpointer;
}

/*
 * Set a double value
 * handle error, incl. termination by other than NULL, space, or newline
 * on error, longjmp (to command loop)
 * a flag determines if value greater than 0 is required
 * a flag determines if argument is mandatory (then longjmp if not present)
 * if argument not mandatory, return NullString if no argument found
 *   otherwise, return string ptr to character following argument
 *     (this may be a string ptr to a '\0' byte)
 * value is only set if found and successful
 */
static char *set_double (char *arguments, double *valuep,
			   int gt_0_req, int arg_req)
{
    char *arg;
    char *beyondpointer = NULL;
    double newvalue;

    arg = strtok (arguments, " ");
    if (!arg) /* No argument present */
    {
	if (arg_req)
	{
	    command_error_message (MISSING_ARGUMENT, arguments);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
	return NullString;
    }
    errno = 0;
    newvalue = strtod (arg, &beyondpointer);
    if (errno || (newvalue  <= 0.0L && gt_0_req))
    {
	command_error_message (BAD_ARGUMENT, arg);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    if (*beyondpointer != ' ' && *beyondpointer != '\0' && 
	*beyondpointer != '\n')    /* illegal character in number */
    {
	command_error_message (BAD_ARGUMENT, beyondpointer);
        RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    *valuep = newvalue;
    return beyondpointer;  /* beyondpointer points to char past arg */
}


static char* get_filename (char *arguments, char **filename_pp)
{
    char *arg;
    char *end;
    char *name;
    char old_endc;
    int len;

    arg = strtok (arguments, "\n");
    if (!arg)
    {
	if (CommandMode == INTERACTIVE_MODE || 
	    CommandMode == WORKBENCH_MODE)
	{
	    *filename_pp = NullString;  /* Default to stdin or stdout */
	    return NullString;
	}
	else
	{
	    command_error_message (MISSING_ARGUMENT, arguments);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
    }
    if (*arg == '\"' || *arg == '\'')  /* filename in quotes */
    {
	end = arg + 1;
	while (*end != '\0' && *end != *arg && *end != '\n')
	{
	    end++;
	}
	if (*end != *arg)
	{
	    command_error_message (BAD_NAME, end);
	    RAISE_ERROR (NOTHING_SPECIAL);
	}
	arg++;         /* Pass initial quote */
    }
    else
    {
	end = arg;
	while (*end != '\0' && *end != ' ' && *end != '\n')
	{
	    end++;
	}
    }
    old_endc = *end;    /* save original termination */
    *end = '\0';        /* terminate name string */
    len = strlen (arg);
    name = gmalloc (len + 1, NOTHING_SPECIAL);    /* Leave room for null! */
    strcpy (name,arg);
    *filename_pp = name;
    if (old_endc != '\0')
    {
	*end++ = old_endc;  /* restore original term, then skip it */
    }
    return end;
}

BOOLEAN is_temp_file (char *filename)
{
    char *template = TEMP_NAME_PREFIX;
    char fchar, tchar;

    if (!filename || filename == NullString)
    {
	return FALSE;
    }

    while (tchar = *template++)
    {
	if (!(fchar = *filename++)) return FALSE;
	if (fchar != tchar) return FALSE;
    }
    return TRUE;
}

ULONG magic_number (char *string)
{
    ULONG magic = 0;

    for (;*string;magic+=*string,string++);
    return magic;
}

char *save_settings (char *arguments)
{
    return save_settings_or_parameters (arguments, FALSE);
}


char *save_parameters (char *arguments)
{
    return save_settings_or_parameters (arguments, TRUE);
}

char *save_settings_or_parameters 
  (char *arguments, BOOLEAN parameters_only)
{
/*
 * This follows much of the same logic as is used for opening a spectrum
 *
 * If a file exists with the same name, it will be renamed to backup.
 * Only one level of backup files is created.
 * It will fail if filesystem does not allow a one character suffix.
 * If the backup fails, file is not opened for output.
 */
    char *more_arguments;
    FILE *temp_ptr = NULL;
    FILE *savefile_ptr = NULL;
    char *savefile_name;

    more_arguments = get_filename (arguments, &savefile_name);
    if (savefile_name == NullString)
    {
	command_error_message (MISSING_ARGUMENT, arguments);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    if (temp_ptr = fopen (savefile_name, "r"))
    {
	int oldlen;
	char *newname;
	int old_backup_deleted = FALSE;
	    
	fclose (temp_ptr);
	oldlen = strlen (savefile_name);
	newname = gmalloc (oldlen + 2, NOTHING_SPECIAL);
	strcpy (newname, savefile_name);
	newname[oldlen] = BACKUP_FILE_CHARACTER;
	newname[oldlen + 1] = '\0';
	if (temp_ptr = fopen (newname,"r"))
	{
	    old_backup_deleted = TRUE;
	    fclose (temp_ptr);
	    remove (newname);
	}
	if (rename (savefile_name, newname))
	{
	    error_message (OUTPUT_BACKUP_FAILURE);
	    RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
	}
	else if (old_backup_deleted)
	{
	    error_message (BACKUP_OVERWRITTEN);  /* Warning only. */
	}
	else
	{
	    error_message (BACKUP_CREATED);  /* Warning only. */
	}
	gfree (newname);
    }
    savefile_ptr = fopen (savefile_name,"w");
    if (!savefile_ptr)
    {
	error_message (CANT_CREATE_OUTPUT_FILE);
	RAISE_ERROR (NOTHING_SPECIAL);  /* longjmp outa here! */
    }
    write_settings (savefile_ptr, NullString, parameters_only, 
		    parameters_only);
    fclose (savefile_ptr);
    return more_arguments;
}

[ RETURN TO DIRECTORY ]