#include <ctype.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <math.h>
#ifndef NOSTDLIB_H
#include <stdlib.h>
#endif
#ifndef NOUNISTD_H
#include <unistd.h>
#endif

#include "symbol.h"
#include "code.h"
#include "macro.h"
#include "math.tab.h"
#include "fudgit.h"
#include "setshow.h"
#include "help.h"
#include "command.h"
#include "readline/history.h"
#include "head.h"

extern FILE *popen(const char *, const char *);
extern int errno;
extern int Ft_Interact;
extern char *strstr(const char *, const char *);
#ifndef AMIGA
extern void exit(int);
#endif
extern int Ft_printversion(void);
extern Ft_mathyyparse(void);

extern int hl_write_history(char *);
extern int hl_append_history(int, char *);
extern HIST_ENTRY **hl_history_list(void);

typedef union {
    double db;
    char* str;
    } Vardesc;

static int Slowterm = 0;
static int balmost(register char *str1, register char *str2);
static int subcommand(int lvl, int argc, char **argv, char *l, Command *cmp);
static int dataread(int argc, char **argv, int exec, Command *cmp);
static int let(int argc, char **argv, char *line, Command *cmp);
static int usage(Command *cmd);
static int splitvar(int ifrom, int xto, char **argv, Vardesc *dbvec,
	int *astringvec, Command *cmp);
static int macrun(Macro *mac, int level);
static void signal_off(void), signal_on(void);

/***********
typedef int Do ();
typedef struct {
    char     *name;
    Do       *func;
    char     *fname;
    char     *usage;
    char     *help;
} Command;
***********/

/* LEVEL 0 COMMANDS */
int Ft_pmode(int c, char **v, char *l, Command *com);
int Ft_help(int c, char **v, char *l, Command *com);

static int do_killplot(int c, char **v, char *l, Command *com);
static int do_list(int c, char **v, char *l, Command *com);
static int do_system(int argc, char **argv, char *line, Command *cmp);
static int do_adjust(int argc, char **argv, char *l, Command *cmp);
static int do_alias(int argc, char **argv, char *line, Command *cmp);
static int go_append(int argc, char **argv, char *l, Command *cmp);
static int do_cd(int argc, char **argv, char *l, Command *cmp);
static int do_cmode(int argc, char **argv, char *l, Command *cmp);
static int do_dumplot(int argc, char **argv, char *l, Command *cmp);
static int do_echo(int argc, char **argv, char *line, Command *cmp);
static int do_end(int c, char **v, char *l, Command *cmp);
static int do_end(int c, char **v, char *l, Command *cmp);
static int do_exec(int c, char **v, char *l, Command *cmp);
static int do_quit(int c, char **v, char *l, Command *cmp);
static int do_fft(int argc, char **argv, char *l, Command *cmp);
static int do_fmode(int c, char **v, char *l, Command *cmp);
static int do_foreach(int argc, char **argv, char *line, Command *cmp);
static int do_free(int argc, char **argv, char *line, Command *cmp);
static int do_let(int c, char **v, char *l, Command *cmp);
static int do_lock(int argc, char **argv, char *l, Command *cmp);
static int do_ls(int argc, char **argv, char *line, Command *cmp);
static int do_pause(int argc, char **argv, char *line, Command *cmp);
static int do_pwd(int argc, char **argv, char *l, Command *cmp);
static int do_read(int c, char **v, char *l, Command *cmp);
static int go_save(int argc, char **argv, char *l, Command *cmp);
static int go_set(int argc, char **argv, char *l, Command *cmp);
static int go_show(int argc, char **argv, char *l, Command *cmp);
static int do_stop(int c, char **v, char *l, Command *cmp);
static int do_unalias(int argc, char **argv, char *l, Command *cmp);
static int do_unlock(int argc, char **argv, char *l, Command *cmp);
static int do_vi(int c, char **v, char *line, Command *cmp);
static int do_load(int argc, char **argv, char *l, Command *cmp);
static int do_fit(int argc, char **argv, char *l, Command *cmp);
#ifndef AMIGA
static int do_hist(int argc, char **argv, char *mode, Command *cmp);
#endif AMIGA
static int do_invfft(int argc, char **argv, char *l, Command *cmp);
static int do_parse(int argc, char **argv, char *line, Command *cmp);
static int do_if(int argc, char **argv, char *line, Command *cmp);
static int do_endif(int argc, char **argv, char *line, Command *cmp);
static int do_else(int argc, char **argv, char *line, Command *cmp);
static int do_while(int argc, char **argv, char *line, Command *cmp);
static int do_udefmac(int argc, char **argv, char *l, Command *cmp);
static int do_defmac(int argc, char **argv, char *l, Command *cmp);
static int do_version(int argc, char **argv, char *l, Command *cmp);
static int do_spline(int argc, char **argv, char *line, Command *cmp);
static int do_smooth(int argc, char **argv, char *l, Command *cmp);
static int do_install(int argc, char **argv, char *l, Command *cmp);

Command Ft_Cmds[] = {
    {"?", do_list, "?", "",
        "display this summary"},
    {"ad!just", do_adjust, "adjust", "value_list",
        "select parameter[s] to adjust in nonlinear fits"},
    {"al!ias", do_alias, "alias", "command command_list",
        "give another name to a command or a list of commands"},
    {"ap!pend", go_append, "append", "object_type [object_list] filename",
        "append different things to a given file"},
    {"cd", do_cd, "cd", "directory",
        "change current working directory"},
    {"cm!ode", do_cmode, "cmode", "[cmode_commands]",
        "switch to C mathematical mode"},
    {"_d!umplot", do_dumplot, "_dumplot", "vector_list",
        "dump given vector[s] to plotting program stdin"},
    {"ec!ho", do_echo, "echo" ,"string",
        "print a string to stdout"},
    {"el!se", do_else, "else", "",
        "fmode style else conditionnal statement"},
    {"end", do_end, "end", "",
        "terminate a do or foreach loop"},
    {"en!dif", do_endif, "endif", "",
        "terminate if conditionnal statement"},
    {"exe!c", do_exec, "exec", "program vector_assignments",
        "assign vector[s] to the output of a program"},
    {"exi!t", do_quit, "exit", "",
        "exit the program"},
    {"fi!t", do_fit, "fit", "dep-VEC indep-VEC [sig-VEC]",
        "fit given vector[s] using pre-selected method and function"},
    {"ff!t", do_fft, "fft", "real-VEC ima-VEC tr-real-VEC tr-ima-VEC",
        "Fourier transform the given vectors"},
    {"fm!ode", do_fmode, "fmode", "",
        "switch to fitting mode from either plotting or C mode"},
    {"fore!ach", do_foreach, "foreach", "Var_Name `in' shell_command\n...\nend",
        "make a macro loop over a series of values"},
    {"fr!ee", do_free, "free", "varname|procname|funcname|\"@all\"...",
        "remove the given object[s] from memory"},
    {"he!lp", Ft_help, "help", "[command]",
        "interactive help"},
#ifndef AMIGA
    {"hi!story", do_hist, "history", "",
        "display complete history"},
#endif
    {"if", do_if, "if", "(condition) `then'",
        "fmode if conditionnal statement"},
    {"ins!tall", do_install, "install", "objfile objname[:|=]name(arg_list)...",
        "link procedures(:) or functions(=) as name()"},
    {"inv!fft", do_invfft, "invfft", "real-VEC ima-VEC tr-real-VEC tr-ima-VEC",
        "Inverse Fourier transform the given vectors"},
    {"_k!illplot", do_killplot, "_killplot", "",
        "kill current plotting program"},
    {"le!t", do_let, "let", "cmode_commands",
        "give a command in C mode from the fitting mode"},
    {"lo!ad", do_load, "load", "filename",
        "read and interpret from command script file"},
    {"loc!k", do_lock, "lock", "variable_list",
        "turn variable[s] into constant[s]"},
    {"ls", do_ls, "ls", "[files]",
        "list files and directories"},
    {"ma!cro", do_defmac, "macro", "name argno\n...\nstop",
        "define a macro"},
    {"parse", do_parse, "parse", "commands",
        "test parsing"},
    {"pa!use", do_pause, "pause", "delay [string]",
        "suspend for the given delay and print string to stderr"},
    {"pm!ode", Ft_pmode, "pmode", "[plotting_commands]",
        "switch to plotting mode"},
    {"pw!d", do_pwd, "pwd", "",
        "print current working directory"},
    {"q!uit", do_quit, "quit", "",
        "same as exit"},
    {"rea!d", do_read, "read", "file vector_assignments",
        "assign vector[s] to column[s] of a file"},
    {"rei!nstall", do_install, "reinstall",
		"objfile objname[:|=]name(arg_list)...",
        "relink procedures(:) or functions(=) as name()"},
    {"sa!ve", go_save, "save", "objet_type [object_list] filename",
        "save specified object[s] to a file"},
    {"se!t", go_set, "set", "object value",
        "set a lot of things"},
    {"she!ll", do_system, "shell", "unix_commands",
        "shell escape bang operator"},
    {"sho!w", go_show, "show", "object_type [object_list]",
        "show a lot of things"},
    {"sm!ooth", do_smooth, "smooth", "sm-factor in-VEC out-VEC",
        "smooth a vector by a given factor"},
    {"sp!line", do_spline, "spline", "XVEC YVEC [dy1] [dyn]",
        "initialize cubic spline interpolation"},
    {"stop", do_stop, "stop", "",
        "indicate end of macro"},
    {"sy!stem", do_system, "system", "unix_commands",
        "shell escape bang operator"},
    {"una!lias", do_unalias, "unalias", "alias_list",
        "undefine an alias"},
    {"unm!acro", do_udefmac, "unmacro", "macro_list",
        "undefine macro"},
    {"unl!ock", do_unlock, "unlock", "constant_list",
        "turn constant[s] into variable[s]"},
    {"ve!rsion", do_version, "version", "",
        "display version number"},
    {"vi", do_vi, "vi", "file_list",
        "call vi editor"},
    {"wh!ile", do_while, "while", "(condition)\n...\nend",
        "while conditionnal loop"},
    {0,      0,        0,         0,       0}
    };

/* FUNCTIONS */
static int do_stfunc(int argc, char **argv, char *l, Command *cmp);

static Command Funcs[] = {
    {"?", do_list, "set function ?", "",
        "display this summary"},
    {"c!osine", do_stfunc, "set function cosine", "",
        "cosine series: n = 1,...N { A[n]*cos(n*X) }"},
    {"e!xponential", do_stfunc, "set function exponential", "",
        "exponential series: n = 2, 4...N { A[n-1]*exp(A[n]*X) }"},
    {"g!aussian", do_stfunc, "set function gaussian", "",
    "Gaussian series: n = 3, 6...N { A[n-2]*exp(A[n-1]*(X-A[n])^2) }"},
    {"l!egendre", do_stfunc, "set function legendre", "",
        "legendre series: n = 1,...N { Pn(X) }"},
    {"p!olynomial", do_stfunc, "set function polynomial", "",
        "power series: n = 1,...N { A[n]*X^(n-1) }"},
    {"u!ser", do_stfunc, "set function user", "definition",
        "user defined function"},
    {"si!ne", do_stfunc, "set function sine", "",
        "sine series: n = 1,...N { A[n]*sin(n*X) }"},
    {"st!raight", do_stfunc, "set function straight_line", "",
        "straight line: { A[1]+A[2]*X }"},
    { 0,     0,        0,        0,        0 }
    };

static int do_stmeth(int argc, char **argv, char *l, Command *cmp);

static Command Meths[] = {
    {"?", do_list, "set method ?", "",
        "display this summary"},
    {"la!_reg", do_stmeth, "set method la_reg", "",
        "least absolute deviation linear regression"},
    {"ls_f!it", do_stmeth, "set method ls_fit", "",
        "least square linear fit"},
    {"ls_r!eg", do_stmeth, "set method ls_reg", "",
        "least square linear regression"},
    {"m!l_fit", do_stmeth, "set method ml_fit", "",
        "Marquardt-Levenberg iterative nonlinear fit"},
    {"s!vd_fit", do_stmeth, "set method svd_fit", "",
        "singular value decomposition linear fit"},
    { 0,     0,        0,        0,        0 }
    };

static int do_stcomm(int argc, char **argv, char *l, Command *cmp);
static int do_stdata(int argc, char **argv, char *l, Command *cmp);
static int do_stdebug(int argc, char **argv, char *l, Command *cmp);
static int do_stslow(int argc, char **argv, char *l, Command *cmp);
static int do_stsamp(int argc, char **argv, char *l, Command *cmp);
static int do_stplotting(int argc, char **argv, char *l, Command *cmp);
static int do_stparam(int argc, char **argv, char *l, Command *cmp);
static int go_stfunc(int argc, char **argv, char *l, Command *cmp);
static int go_stmeth(int argc, char **argv, char *l, Command *cmp);
static int do_stform(int argc, char **argv, char *l, Command *cmp);
static int do_stiter(int argc, char **argv, char *l, Command *cmp);
static int do_stpager(int argc, char **argv, char *l, Command *cmp);
static int do_stexp(int argc, char **argv, char *l, Command *cmp);
static int do_stnexp(int argc, char **argv, char *l, Command *cmp);
static int do_stpromptcm(int argc, char **argv, char *l, Command *cmp);
static int do_stpromptfm(int argc, char **argv, char *l, Command *cmp);
static int do_stpromptpm(int argc, char **argv, char *l, Command *cmp);
static int do_stvform(int argc, char **argv, char *l, Command *cmp);
static int do_stoutput(int argc, char **argv, char *l, Command *cmp);
static int do_stinput(int argc, char **argv, char *l, Command *cmp);
static int do_sterr(int argc, char **argv, char *l, Command *cmp);

static Command Sets[] = {
    {"?", do_list, "set ?", "",
        "display this summary"},
    {"c!omment", do_stcomm, "set comment", "character",
        "change comment escape character (default: '#')"},
    {"da!ta", do_stdata, "set data", "integer",
        "set current vector size"},
    {"de!bug", do_stdebug, "set debug", "integer_list",
        "select and toggle debugging levels"},
    {"er!ror", do_sterr, "set error", "value",
        "define type of math error check"},
    {"ex!pand", do_stexp, "set expand", "",
        "allow history expansion"},
    {"fo!rmat", do_stform, "set format", "string",
        "change number display format (default: \"% 10.8e\")"},
    {"fu!nction", go_stfunc, "set function", "string [userdef]",
        "set function to fit"},
    {"in!put", do_stinput, "set input", "filename",
        "select cmode 'read' command input file"},
    {"it!eration", do_stiter, "set iteration", "integer",
        "set iteration number for nonlinear fits (default: 10)"},
    {"m!ethod", go_stmeth, "set method", "string",
        "select fitting method"},
    {"noex!pand", do_stnexp, "set noexpand", "",
        "disable history expansion"},
    {"ou!tput", do_stoutput, "set output", "filename",
        "select cmode 'print' command output file"},
    {"pag!er", do_stpager, "set pager", "pager_name",
        "select pager (default: PAGER environement)"},
    {"par!ameters", do_stparam, "set parameters", "NAME size",
        "define parameter list to be NAME[1] to NAME[size]"},
    {"pl!otting", do_stplotting, "set plotting", "string",
        "select plotting program (default: /usr/local/bin/gnuplot)"},
    {"prompt-cm", do_stpromptcm, "set prompt-cm", "string",
        "select C-calculator mode prompt (default: \"cmode> \")"},
    {"prompt-fm", do_stpromptfm, "set prompt-fm", "string",
        "select fitting mode prompt (default: \"fudgit> \")"},
    {"prompt-pm", do_stpromptpm, "set prompt-pm", "string",
        "select plotting mode prompt (default: \"pmode> \")"},
    {"sa!mples", do_stsamp, "set samples", "integer",
        "change vector maximum capacity (default: 4000)"},
    {"sl!owterm", do_stslow, "set slowterm", "",
        "toggle prompt after system command"},
    {"vf!ormat", do_stvform, "set vformat", "string",
        "change format for number expansion (default: \"%.3g\")"},
    { 0,     0,        0,        0,        0 }
    };

static int do_shcomm(int argc, char **argv, char *l, Command *cmp);
static int do_shdata(int argc, char **argv, char *l, Command *cmp);
static int do_shdebug(int argc, char **argv, char *l, Command *cmp);
static int do_shslow(int argc, char **argv, char *l, Command *cmp);
static int do_shsamp(int argc, char **argv, char *l, Command *cmp);
static int do_shplotting(int argc, char **argv, char *l, Command *cmp);
static int do_shfunc(int argc, char **argv, char *l, Command *cmp);
static int do_shmeth(int argc, char **argv, char *l, Command *cmp);
static int do_shform(int argc, char **argv, char *l, Command *cmp);
static int do_shiter(int argc, char **argv, char *l, Command *cmp);
static int do_shpager(int argc, char **argv, char *l, Command *cmp);
static int do_shfit(int argc, char **argv, char *l, Command *cmp);
static int do_shtab(int argc, char **argv, char *l, Command *cmp);
static int do_shmem(int argc, char **argv, char *l, Command *cmp);
static int do_shvform(int argc, char **argv, char *l, Command *cmp);
static int do_svvec(int argc, char **argv, char *mode, Command *cmp);
static int do_shmac(int argc, char **argv, char *l, Command *cmp);
static int do_svpar(int argc, char **argv, char *mode, Command *cmp);
static int do_shsetup(int argc, char **argv, char *l, Command *cmp);
static int do_svvar(int argc, char **argv, char *mode, Command *cmp);
static int do_shexp(int argc, char **argv, char *l, Command *cmp);
static int do_shpromptcm(int argc, char **argv, char *l, Command *cmp);
static int do_shpromptfm(int argc, char **argv, char *l, Command *cmp);
static int do_shpromptpm(int argc, char **argv, char *l, Command *cmp);
static int do_shoutput(int argc, char **argv, char *l, Command *cmp);
static int do_shinput(int argc, char **argv, char *l, Command *cmp);
static int do_sherr(int argc, char **argv, char *l, Command *cmp);

static Command Shows[] = {
    {"?", do_list, "show ?", "",
        "display this summary"},
    {"c!omment", do_shcomm, "show comment", "",
        "display current comment escape character"},
    {"da!ta", do_shdata, "show data", "",
        "show current vector size"},
    {"de!bug", do_shdebug, "show debug", "",
        "display current debugging levels"},
    {"er!ror", do_sherr, "show error", "",
        "display type of math error check"},
    {"ex!pansion", do_shexp, "show expansion", "",
        "display current expansion value"},
    {"fi!t", do_shfit, "show fit", "",
        "complete display of last fit results"},
    {"fo!rmat", do_shform, "show format", "",
        "show current number display format"},
    {"fu!nction", do_shfunc, "show function", "",
        "show current function to fit"},
    {"in!put", do_shinput, "show input", "",
        "display cmode 'read' active input file"},
    {"it!eration", do_shiter, "show iteration", "",
        "show active iteration number for nonlinear fits"},
    {"ma!cros", do_shmac, "show macros", "[macro_name]",
        "display definitions of one or all active macros"},
    {"mem!ory", do_shmem, "show memory", "",
        "display complete state of allocated memory"},
    {"met!hod", do_shmeth, "show method", "",
        "display selected fitting method"},
    {"o!utput", do_shoutput, "show output", "",
        "display cmode 'print' active output file"},
    {"pag!er", do_shpager, "show pager", "",
        "display active pager"},
    {"par!ameters", do_svpar, "show parameters", "[variable_list]",
        "show selected parameter list"},
    {"pl!otting", do_shplotting, "show plotting", "",
        "show selected plotting program"},
    {"prompt-cm", do_shpromptcm, "show prompt-cm", "",
        "select C-calculator mode prompt"},
    {"prompt-fm", do_shpromptfm, "show prompt-fm", "",
        "select fitting mode prompt"},
    {"prompt-pm", do_shpromptpm, "show prompt-pm", "",
        "select plotting mode prompt"},
    {"sa!mples", do_shsamp, "show samples", "",
        "show current vector maximum capacity"},
    {"sl!owterminal", do_shslow, "show slowterminal", "",
        "show current state of slow terminal switch"},
    {"se!tup", do_shsetup, "show setup", "",
        "display current setup"},
    {"va!riables", do_svvar, "show variables", "variable_list",
        "display contents of selected variables"},
    {"ve!ctors", do_svvec, "show vector", "vector_list",
        "display contents of selected vectors"},
    {"vf!ormat", do_shvform, "show vformat", "",
        "show current string expansion format of numbers"},
    {"t!able", do_shtab, "show table", "",
        "display state of internal symbol lookup table"},
    { 0,    0,        0,        0,        0}
    };

#ifndef AMIGA
static int do_svhist(int argc, char **argv, char *mode, Command *cmp);
#endif
static int do_svvec(int argc, char **argv, char *mode, Command *cmp);
static int do_svvar(int argc, char **argv, char *mode, Command *cmp);
static int do_svmac(int argc, char **argv, char *mode, Command *cmp);
static int do_svpar(int argc, char **argv, char *mode, Command *cmp);

static Command Saves[] = {
    {"?", do_list, "save ?", "",
        "display this summary"},
#ifndef AMIGA
    {"h!istory", do_svhist, "save history", "filename",
        "save all of history to a file"},
#endif
    {"m!acros", do_svmac, "save macros", "filename",
        "save all active macro definitions to a file"},
    {"p!arameters", do_svpar, "save parameters", "[variable_list] filename",
        "save all parameters and errors to a file"},
    {"va!riables", do_svvar, "save variables", "variable_list filename",
        "save specified variables to a file"},
    {"ve!ctors", do_svvec, "save vectors", "vector_list filename",
        "save specified vectors to a file"},
    { 0,    0,        0,            0,        0}
    };

static Command Appends[] = {
    {"?", do_list, "append ?", "",
        "display this summary"},
#ifndef AMIGA
    {"h!istory", do_svhist, "append history", "filename",
        "append all of history to a file"},
#endif
    {"m!acros", do_svmac, "append macros", "filename",
        "append all active macro definitions to a file"},
    {"p!arameters", do_svpar, "append parameters", "[variable_list] filename",
        "append all parameters and errors to a file"},
    {"va!riables", do_svvar, "append variables", "variable_list filename",
        "append specified variables to a file"},
    {"ve!ctors", do_svvec, "append vectors", "vector_list filename",
        "append specified vectors to a file"},
    { 0,    0,        0,        0,        0}
    };

/* HERE WE START */

int Ft_exit (int val);
int Ft_almost (register char *str1, register char *str2);

extern int Ft_iolevel (void);
extern int Ft_popio (void);
extern int Ft_killplot (void);
extern int Ft_fits (int argc, char **argv, int ndata);
extern int Ft_pushio (char *string, int type, char *name);
extern int Ft_varcpy (char *, char *);
extern int Ft_readvar (char **argp, Symbol **sym, int *loc, int (*irange)[32], double (*range)[32], int *lines, int num, int exec, char *comname);
extern int Ft_dumplot (double **dblv, int ndata);
extern int Ft_processline (char *lp);
extern int Ft_run_smooth (int argc, char **argv, int ndata);
extern int Ft_run_fft (int argc, char **argv, int dir, int ndata);
#ifndef HPUX
extern int killpg (int, int);
#endif
extern int Ft_setparam (char *name, int n);
extern int Ft_symremove (char *name, int verb);
extern int Ft_clearpush_cwd (void);
extern void Ft_initmathyylex (char *str);
extern int Ft_save_macros (int type, char *name, char *mode);
extern int Ft_showmac (int argc, char **argv, int type);
extern int Ft_showsetup (void);
extern int Ft_showfit (void);
extern int Ft_showmem (void);
extern int Ft_showtable (void);
extern int Ft_more_input (int level, char *iprompt);
extern int Ft_macremove (char *name, int type);
extern int Ft_lock (int i, char *name, char *fname);
extern int Ft_switchif (int val);
extern int Ft_pushif (int val);
extern int Ft_popif (void);
extern int Ft_spline (double *x, double *y, double yp1, double ypn, int n);

int Ft_command(int argc, char **argv, char *line)
{
    int i;
    Command *cmp = Ft_Cmds;

    if (argv[0][0] == '!') {
        line[0] = ' ';  /* erase the bang */
        return(do_system(0, argv, line, 0));
    }   
    for (i=0; Ft_Cmds[i].name; i++, cmp++)
        if (balmost(argv[0], Ft_Cmds[i].name))
            return(Ft_Cmds[i].func(argc, argv, line, cmp));
   
    fprintf(stderr, "%s: Command not found.\n", argv[0]);
    return(ERRR);
}

static int do_list(int c, char **v, char *l, Command *com)
{
    int i;
    FILE *fp = stdout;
    char *cp;

#ifndef AMIGA
     if (c == 1 && Ft_Interact && *Ft_Pager) {
        if ((fp = popen(Ft_Pager, "w")) == (FILE *)NULL)  {
            fprintf(stderr, "Warning: Could not open pager %s.\n", Ft_Pager);
            fp = stdout;
        }
    }
#endif AMIGA
    for (i=0; com[i].name; i++) {
        if ((cp = strrchr(com[i].fname, ' ')) == NULL)
            cp = com[i].fname;
        fprintf(fp, "%14s: %s;\n", cp, com[i].help);
    }
    if (fp != stdout) {
		fflush(fp);
		pclose(fp);
	}
   
    return(0);
}

static int do_end(int c, char **v, char *l, Command *cmp)
{
    fprintf(stderr, "%s: Not in `foreach' or `while' loop.\n", cmp->fname);
    return(ERRR);
}

static int do_fmode(int c, char **v, char *l, Command *cmp)
{
    fprintf(stderr,
    "Warning: %s: Program already in fitting mode: Line ignored.\n",
	cmp->fname);
    return(0);
}

static int do_killplot(int c, char **v, char *l, Command *cmp)
{
	extern int Ft_killplot(void);

	return(Ft_killplot());
}

static int do_stop(int c, char **v, char *l, Command *cmp)
{
    fprintf(stderr, "Warning: %s: Not in macro.\n", cmp->fname);
    if (Ft_iolevel())
        Ft_popio();
    return(0);
}

static int do_let(int c, char **v, char *l, Command *cmp)
{
    return(let(c, v, l, cmp));
}

static int do_read(int c, char **v, char *l, Command *cmp)
{
    return(dataread(c, v, 0, cmp));
}

static int do_exec(int c, char **v, char *l, Command *cmp)
{
    return(dataread(c, v, 1, cmp));
}

static int do_quit(int c, char **v, char *l, Command *cmp)
{
    return(Ft_exit(0));
}

int Ft_exit(int val)
{
    char buffer[512];

    signal_off();
    signal(SIGQUIT, SIG_IGN);
    Ft_killplot();
    fclose(Ft_Outprint);
    signal(SIGCHLD, SIG_IGN);
#ifdef AMIGA
    printf("temporary file(s) called t:fudgit%d* may be left...", getpid());
#else
    sprintf(buffer, "exec /bin/rm -f /tmp/fudgit%d*", getpid());
#endif
    system(buffer);
	sprintf(buffer, "%s/%s", Ft_Home, HISTORY);
#ifndef AMIGA
	if (Ft_Interact) hl_write_history(buffer);
#endif
    if (val == 2) {
        fputs("Do you know why I received that signal?\nIf not report that bug!\n\n", stderr);
    }
    if (val > 1) {
        signal(SIGTERM, SIG_IGN);
#ifdef HPUX
        kill( -getpid(), SIGTERM);
#else
        killpg(getpid(), SIGTERM);
#endif
    }
    exit(val);
}

/* BALMOST UTILITY */
static int balmost(register char *str1, register char *str2)  /* account for built-in functions */
                           
{
    if (*str1 == '&')
        str1++;
    return(Ft_almost(str1, str2));
}

/* ALMOST UTILITY  */
int Ft_almost(register char *str1, register char *str2)
{
    int ok = 0;
    register int i = 0;
   
    while (*str1 != ' ' && *str1 != '\t' && *str1 != '\n' &&
    *str1 != '\0' && i++ < TOKENSIZE) { /* avoid runaway  */
        if (*str1 != *str2) {
            if (*str2 != '!') {
                return(0);
            }
            else {
                ok = 1;
                str2++;;
                continue;
            }
        }
        str1++;
        str2++;
    }
    return(ok || *str2 == '!' || *str2 == '\0');
}

/*  DO_SET FUNCTION  */
static int go_set(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 2 && argv[1][0] == '?')
        return(do_list(argc, argv, l, Sets));
    return(subcommand(1, argc, argv, l, Sets));
}

/*  DO_SHOW FUNCTION  */
static int go_show(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 2 && *argv[1] == '?')
        return(do_list(argc, argv, l, Shows));
    return(subcommand(1, argc, argv, "s", Shows));
}

/*  DO_APPEND FUNCTION  */
static int go_append(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 2 && *argv[1] == '?')
        return(do_list(argc, argv, l, Appends));
    return(subcommand(1, argc, argv, "a", Appends));
}

/*  DO_SAVE FUNCTION  */
static int go_save(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 2 && *argv[1] == '?')
        return(do_list(argc, argv, l, Saves));
    return(subcommand(1, argc, argv, "w", Saves));
}

/*  DO_SET_FUNCTION FUNCTION  */
static int go_stfunc(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 3 && *argv[2] == '?')
        return(do_list(argc, argv, l, Funcs));
    return(subcommand(2, argc, argv, l, Funcs));
}

/*  DO_SET_METHOD FUNCTION  */
static int go_stmeth(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 3 && *argv[2] == '?')
        return(do_list(argc, argv, l, Meths));
    return(subcommand(2, argc, argv, l, Meths));
}

static int subcommand(int lvl, int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc <= lvl) {
        fputs("Command incomplete.\n", stderr);
        return(ERRR);
    }
    for (i=0; cmp->name; i++, cmp++)
        if (Ft_almost(argv[lvl], cmp->name))
            return(cmp->func(argc, argv, l, cmp));
   
    fprintf(stderr, "%s: Name not found.\n", argv[lvl]);
    return(ERRR);
}

/* VERSION */
static int do_version(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 1)
        return(usage(cmp));
    return(Ft_printversion());
}

/* COMMENT */
static int do_stcomm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    if (argv[2][1] != '\0') {
        fprintf(stderr, "%s: Not a character.\n", argv[2]);
        return(ERRR);
    }
    Ft_Comchar = argv[2][0];
    return(0);
}

static int do_shcomm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%c\n", Ft_Comchar);
    return(0);
}

/* DEBUG */
static int do_stdebug(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 2 || argv[2][0] == '?') {
        fputs("Debugging levels:\n", stderr);
        fputs("\t 0: Clear debugging bits.\n", stderr);
        fputs("\t 1: Echo expanded input lines.\n", stderr);
        fputs("\t 2: Echo raw input lines.\n", stderr);
        fputs("\t 3: Display ignored line numbers while reading data.\n",
        stderr);
        fputs("\t 4: Echo input lines passed to math parser.\n", stderr);
        fputs("\t 5: Debug parser (if compiled with -DYYDEBUG).\n", stderr);
        fputs("\t 6: Trace `if' constructions.\n", stderr);
    }
    else {  /* must be larger than 2 */
        float fldeb;
        int deb;
        int i;
#ifdef YYDEBUG
        extern int Ft_mathyydebug;
#endif

        for (i=2;i<argc;i++) {
            if (sscanf(argv[i], "%f", &fldeb) != 1) {
                fprintf(stderr, "%s: Could not read number \"%s\".\n",
                cmp->fname, argv[i]);
                return(ERRR);
            }
            deb = (int)fldeb;
            if (deb)
                Ft_Debug |= 01<<(deb-1);
            else
                Ft_Debug = 0;
        }
#ifdef YYDEBUG
        Ft_mathyydebug = (Ft_Debug & DEBUG_PARSER);
#endif
    }
    return(0);
}

static int do_shdebug(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%o\n", Ft_Debug);
    return(0);
}

/* VFORMAT */
static int do_stvform(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    sprintf(Ft_Vformat, "%s", argv[2]);
    return(0);
}

/* FORMAT */
static int do_stform(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    sprintf(Ft_Format, "%s", argv[2]);
    sprintf(Ft_TFormat, "\t%s", argv[2]);
    return(0);
}

static int do_shvform(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "\"%s\"\n", Ft_Vformat);
    return(0);
}

static int do_shform(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "\"%s\"\n", Ft_Format);
    return(0);
}

/* FUNCTION */
static int do_stfunc(int argc, char **argv, char *l, Command *cmp)
{
    int i;
    char *cp;

    if (argc != 3)
        return(usage(cmp));
    for (i=0;i<FUNCNUM;i++) {  /* look twice I know!... */
        if (Ft_almost(argv[2], Ft_Function[i].cname)) {
            Ft_Funci = i;
            break;
        }
    }
    if (Ft_Funci != USER)
        return(0);
    /* DO USER */
    if ((cp = Ft_readmacro("user? ")) == NULL) {
        return(ERRR);
    }
    sprintf(Ft_UFunction, "%s", cp);
    return(0);
}

static int do_shfunc(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    if (Ft_Funci == USER)
        fprintf(stdout, "user:\n{\n%s}\n", Ft_UFunction);
    else
        fprintf(stderr, "%s\n", Ft_Function[Ft_Funci].name);

    return(0);
}

/* ITER */
static int do_stiter(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc != 3)
        return(usage(cmp));
    if (sscanf(argv[2], "%d", &i) != 1) {
        fprintf(stderr, "%s: Could not read value %s.\n",
        cmp->fname, argv[2]);
        return(ERRR);
    }
    Ft_Iter = i;
    return(0);
}

static int do_shiter(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%d\n", Ft_Iter);
    return(0);
}

/* OUTPUT */
static int do_stoutput(int argc, char **argv, char *l, Command *cmp)
{
    extern FILE *Ft_Outprint;
    extern char Ft_Outname[];

    if (argc != 3)
        return(usage(cmp));
    if (Ft_Outprint != stderr && Ft_Outprint != stdout) {
        fflush(Ft_Outprint);
        fclose(Ft_Outprint);
    }
    if (Ft_almost(argv[2], "stdout")) {
        sprintf(Ft_Outname, "stdout");
        Ft_Outprint = stdout;
        return(0);
    }
    if (Ft_almost(argv[2], "stderr")) {
        sprintf(Ft_Outname, "stderr");
        Ft_Outprint = stderr;
        return(0);
    }
    if ((Ft_Outprint = fopen(argv[2], "w")) == (FILE *)NULL) {
        fprintf(stderr, "%s: %s: Permission denied.\n", cmp->fname, argv[2]);
        sprintf(Ft_Outname, "stdout");
        Ft_Outprint = stdout;
        return(ERRR);
    }
    sprintf(Ft_Outname, "%s", argv[2]);
    return(0);
}

/* INPUT */
static int do_stinput(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    if (Ft_Inread != stdin) {
        fclose(Ft_Inread);
    }
    if (Ft_almost(argv[2], "stdin")) {
        sprintf(Ft_Inname, "stdin");
        Ft_Inread = stdin;
        return(0);
    }
    if ((Ft_Inread = fopen(argv[2], "r")) == (FILE *)NULL) {
        fprintf(stderr, "%s: %s: Permission denied.\n", cmp->fname, argv[2]);
        sprintf(Ft_Inname, "stdin");
        Ft_Inread = stdin;
        return(ERRR);
    }
    sprintf(Ft_Inname, "%s", argv[2]);
    return(0);
}

static int do_shoutput(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%s\n", Ft_Outname);
    return(0);
}

static int do_shinput(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%s\n", Ft_Inname);
    return(0);
}

/* PAGER */
static int do_stpager(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    sprintf(Ft_Pager, "%s", argv[2]);
    return(0);
}

static int do_shpager(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%s\n", Ft_Pager);
    return(0);
}

/* PLOTTING */
static int do_stplotting(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc < 3)
        return(usage(cmp));
    for (i=0;i<argc-2 && i < MAXPARG-1;i++) {
        sprintf(Ft_Plotting[i], "%s", argv[i+2]);
    }
    Ft_Plotting[i][0] = '\0';
    Ft_killplot();
    return(0);
}

static int do_shplotting(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc != 2)
        return(usage(cmp));
    for (i=0;Ft_Plotting[i][0] != '\0' && i < MAXPARG-1;i++) {
        fprintf(stderr, "%s ", Ft_Plotting[i]);
    }
    fputc('\n', stderr);
    return(0);
}

/* DATA */
static int do_stdata(int argc, char **argv, char *l, Command *cmp)
{
    extern double *Ft_Data;
    int i;

    if (argc != 3)
        return(usage(cmp));
    if (sscanf(argv[2], "%d", &i) != 1) {
        fprintf(stderr, "%s: Could not read value %s.\n",
        cmp->fname, argv[2]);
        return(ERRR);
    }
    if (i<1 || i > Ft_Samples) {
        fprintf(stderr, "%s: Value out of current capacity.\n",
        cmp->fname);
        fputs("Enlarge with `set samples' first.\n", stderr);
        return(ERRR);
    }
    else if (i < (int) *Ft_Data) {
        fprintf(stderr, "Warning: possible hidden data (%d -> %d).\n",
        (int) *Ft_Data, i);
    }
    *Ft_Data = (double)i;
    return(0);
}

static int do_shdata(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%d\n", (int) *Ft_Data);
    return(0);
}

/* METHOD */
static int do_stmeth(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc != 3)
        return(usage(cmp));
    for (i=0;i< METHNUM;i++) {  /* twice again...*/
        if (Ft_almost(argv[2], Ft_Method[i].cname)) {
            Ft_Methi = i;
            return(0);
        }
    }
    fprintf(stderr, "%s: Invalid option.\n.", argv[2]);
    return(ERRR);
}

static int do_shmeth(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%s\n", Ft_Method[Ft_Methi].name);
    return(0);
}

/* PARAMETERS */
static int do_stparam(int argc, char **argv, char *l, Command *cmp)
{
    float flnumber;

    if (argc != 4)
        return(usage(cmp));
    if (sscanf(argv[3], "%f", &flnumber) != 1) {
        fprintf(stderr, "%s: Could not read number \"%s\".\n",
        cmp->fname, argv[3]);
        return(ERRR);
    }
    if (Ft_setparam(argv[2], (int)flnumber) == ERRR) {
        fprintf(stderr,
        "%s: Could not set parameter \"%s\".\n", cmp->fname, argv[2]);
        return(ERRR);
    }
    return(0);
}

/* SAMPLES */
static int do_stsamp(int argc, char **argv, char *l, Command *cmp)
{
    float flvalue;
    int value;

    if (argc != 3)
        return(usage(cmp));
    if (sscanf(argv[2], "%f", &flvalue) != 1) {
        fprintf(stderr, "%s: Could not read number \"%s\".\n",
        cmp->fname, argv[2]);
        return(ERRR);
    }
    value = (int)flvalue;
    if (value < 1) {
        fprintf(stderr, "%s: %d: Illegal value.\n", cmp->fname, value);
        return(ERRR);
    }
    Ft_symremove("@all", 0);
    Ft_Samples = value;
    return(0);
}

static int do_shsamp(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%d\n", Ft_Samples);
    return(0);
}

/* SLOWTERM */
static int do_stslow(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    Slowterm = !Slowterm;
    return(0);
}

/* SLOWTERM */
static int do_shslow(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%s\n", Slowterm? "on": "off");
    return(0);
}

/* DO_CD FUNCTION */
static int do_cd(int argc, char **argv, char *l, Command *cmp)
{
    extern char Ft_Cwd[PATH_MAXIM];
#ifndef HPUX   /*  HPUX  use getcwd() for HPUX -- it has no getwd()  */
    extern char *getwd(char *);
#endif  /*  HPUX  */

    switch (argc) {
        case 1:
            if (chdir(Ft_Home) == ERRR) {
                fprintf(stderr, "%s: ", Ft_Home);
                perror("");
                return(ERRR);
            }
            break;
        case 2:
            if (chdir(argv[1]) == ERRR) {
                fprintf(stderr, "chdir: %s: ", argv[1]);
                perror("");
                return(ERRR);
            }
            break;
        default:
            return(usage(cmp));
    }

#ifdef HPUX   /* HPUX  uses getcwd()  */
    if (getcwd(Ft_Cwd, PATH_MAXIM-1) == (char *) NULL) {
        perror("getcwd");
#else
    if (getwd(Ft_Cwd) == (char *)NULL) {
		/* getwd places an error message in Cwd */
        fprintf(stderr, "%s\n", Ft_Cwd);
#endif  /* HPUX  */
        return(ERRR);
    }
    else if (Ft_Interact) {
	/* NeXT sometimes echoes it */
#ifndef NEVER
        fprintf(stderr, "%s\n", Ft_Cwd);
#endif
    }
    Ft_clearpush_cwd();
    return(0);
}

/* DO_FREE FUNCTION */
static int do_free(int argc, char **argv, char *line, Command *cmp)
{
    int i;

    if (argc == 1)
        return(usage(cmp));
    for (i=1;i<argc;i++) {
        Ft_symremove(argv[i], 1);
    }
    return(0);
}

/* DO_PAUSE FUNCTION  */
static int do_pause(int argc, char **argv, char *line, Command *cmp)
{
    int value;
    float flvalue;

    if (argc < 2)
        return(usage(cmp));

    if (argc > 2) {
        char *cp;

        cp = line + strlen(argv[0]) + strlen(argv[1]) + 2;
        line[strlen(line)-1] = '\0';
        fprintf(stderr, "%s ", cp);
        fflush(stderr);
    }
    if (sscanf(argv[1], "%f", &flvalue) != 1) {
        fprintf(stderr, "%s: Could not read number \"%s\".\n",
        cmp->fname, argv[1]);
        return(ERRR);
    }
    if ((value = (int)flvalue) >= 0) {
        sleep(value);
        fputc('\n', stderr);
        fflush(stderr);
    }
    else {
        char fromline[LINESIZE];

        fgets(fromline, LINESIZE, stdin);
    }
    return(0);
}

/* DO_PWD FUNCTION  */
static int do_pwd(int argc, char **argv, char *l, Command *cmp)
{
    extern char Ft_Cwd[PATH_MAXIM];

    if (argc != 1)
        return(usage(cmp));

    fprintf(stderr, "%s\n", Ft_Cwd);
    return(0);
}

/* DO_LS FUNCTION */
static int do_ls(int argc, char **argv, char *line, Command *cmp)
{
    char fromline[LINESIZE +16];
    int  val;

    signal_off();
    if (argc == 1) {
        val = system("exec ls -FC");
    }
    else {
        char *cp;

        cp = line + strlen(argv[0]) + 1;
        sprintf(fromline, "exec ls -FC %s", cp);
        val = system(fromline);
    }
    signal_on();
    if (Slowterm && Ft_Interact && !Ft_iolevel()) {
        fputs("\nHit return to continue", stdout);
        fgets(fromline, LINESIZE, stdin);
    }
    return(val);
}

/* LET FUNCTION */
static int let(int argc, char **argv, char *line, Command *cmp)
{
    char *argp;
	void Ft_let(char *string);

    if (argc == 1)
        return(usage(cmp));
    if (argc == 0) {
        argp = line;
    }
    else {
        argp = line + strlen(argv[0]) + 1;
    }
	Ft_let(argp);
    return(0);
}

void Ft_let(char *string)
{
	Ft_initcode();
	Ft_initmathyylex(string);
	Ft_mathyyparse();
}

/* DO_SAVE FUNCTIONS */
#ifndef AMIGA
static int do_svhist(int argc, char **argv, char *mode, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    if (*mode == 'w')
        return(hl_write_history(argv[2]) ? ERRR: 0);
    return(hl_append_history(512, argv[2]) ? ERRR: 0);
}

static int do_hist(int argc, char **argv, char *mode, Command *cmp)
{
    HIST_ENTRY **h_list;
	FILE *fp = stderr;
    int i;

    if (argc > 2)
        return(usage(cmp));
    if ((h_list = hl_history_list())) {
		if (Ft_Interact && *Ft_Pager) {
           if ((fp = popen(Ft_Pager, "w")) == (FILE *)NULL)  {
                fprintf(stderr, "Warning: %s: Could not open pager %s.\n",
                cmp->fname, Ft_Pager);
                fp = stderr;
            }
        }
        for (i=0; h_list[i]; i++) {
            fprintf(fp, "%d: %s\n", (i + hl_history_base), h_list[i]->line);
        }
    }
	if (fp != stderr) {
		fflush(fp);
		pclose(fp);
	}

    return(0);
}
#endif

/* MACROS  */
static int do_svmac(int argc, char **argv, char *mode, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    return(Ft_save_macros(AMACRO, argv[2], mode));
}

/* SHOW FUNCTIONS */
static int do_shmac(int argc, char **argv, char *l, Command *cmp)
{
    if (argc > 3)
        return(usage(cmp));
    return(Ft_showmac(argc, argv, AMACRO));
}

/* SETUP */
static int do_shsetup(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 1)
        return(usage(cmp));
    return(Ft_showsetup());
}

/* FIT  */
static int do_shfit(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 1)
        return(usage(cmp));
    return(Ft_showfit());
}

/* MEMORY */
static int do_shmem(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
#if !defined(NOMALLINFO)
    return(Ft_showmem());
#else
	fprintf(stderr, "%s: Function not supported.\n", cmp->fname);
	return(ERRR);
#endif
}

/* TABLE */
static int do_shtab(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    return(Ft_showtable());
}

/* DO_ECHO FUNCTION */
static int do_echo(int argc, char **argv, char *line, Command *cmp)
{
    if (argc == 1) {
        fputc('\n', stdout);
    }
    else {
        char *cp;

        cp = line + strlen(argv[0]) + 1;
        fputs(cp, stdout);
    }
    return(0);
}

/* DO_SYSTEM FUNCTION */
static int do_system(int argc, char **argv, char *line, Command *cmp)
{
    int val;
    char fromline[80];
    extern char Ft_Shell[];
    extern int errno;

    errno = 0;
    signal_off();
    switch (argc) {
        case 0:
            val = system(line);
            break;
        case 1:
            sprintf(fromline, "exec %s", Ft_Shell);
            val = system(fromline);
			fputc('\n', stderr);
            break;
        default:
            val = system((line + strlen(argv[0]) + 1));
            break;
    }
    signal_on();
    if (Slowterm && Ft_Interact && !Ft_iolevel()) {
        fputs("\nHit return to continue", stdout);
        fgets(fromline, 80, stdin);
    }
    if (val) {
        if (val == ERRR)
            perror("system");
        else
            fputs("Warning: System returned an error.\n", stderr);
        return(ERRR);
    }
    return(0);
}

/* DO_VI FUNCTION */
static int do_vi(int c, char **v, char *line, Command *cmp)
{
    signal_off();
    system(line);
    signal_on();
    return(0);
}

/* DO_FIT FUNCTION  */
static int do_fit(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 4 && (argc != 3 || (Ft_Methi != LS_REG && Ft_Methi != LA_REG)))
        return(usage(cmp));
    return(Ft_fits(argc, argv, (int) *Ft_Data));
}

/* DO_ADJUST FUNCTION */
static int do_adjust(int argc, char **argv, char *l, Command *cmp)
{
    int i, j;
    float flj;

    if (argc < 2 || (int) *Ft_Param < argc - 1) {
        fprintf(stderr, "%s: Invalid number of parameters.\n",
        cmp->fname);
        return(ERRR);
    }
    else if (Ft_Methi != ML_FIT && Ft_Methi != LS_FIT) {
        fprintf(stderr, "%s: Warning: Not active under `%s' method.\n",
        cmp->fname, Ft_Method[Ft_Methi].name);
    }
    for (i=1;i < argc; i++) {
        if (sscanf(argv[i], "%f", &flj) != 1) {
            fprintf(stderr, "%s: Could not read number \"%s\".\n",
            cmp->fname, argv[i]);
            return(ERRR);
        }
        j = (int)flj;
        if (j<1 || j> (int) *Ft_Param) {
            fprintf(stderr, "%s: Invalid parameter %d.\n",
            cmp->fname, j);
            Ft_Mlist = 0;
            return(ERRR);
        }
        Ft_Miparx1[i] = j;
    }
    Ft_Mlist = i -1;
    return(0);
}

/* DO_LOAD FUNCTION */
static int do_load(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    return(Ft_pushio(argv[1], AFILE, (char *) 0));
}

/* DO_READ FUNCTION  */
static int dataread(int argc, char **argv, int exec, Command *cmp)
{
    int i;
    char *sc;
    char name[TOKENSIZE];
    Symbol *table[MAXVAR];
    int loctable[MAXVAR];
    int irange[2][MAXVAR];
    int lines[2];
    double range[2][MAXVAR];
    extern Symbol *Ft_lookup(char *);
    extern double strtod(const char *, char **);

    if (argc < 3)
        return(usage(cmp));
    if (argc > MAXVAR) {
        fprintf(stderr, "%s: %d: Too many variables.\n",
        cmp->fname, argc-2);
        return(ERRR);
    }
    lines[0] = 0;
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
    lines[1] = INT_MAX;
    for (i=0; i<argc-2;i++) {
        if (sscanf(argv[i+2], "%[^:]:%d", name, &loctable[i]) != 2) {
            fprintf(stderr, "%s: Bad argument \"%s\".\n",
            cmp->fname, argv[i+2]);
            return(ERRR);
        }
        if ((table[i] = Ft_lookup(name)) == 0) {
            if (Ft_varcpy(0, name) != VEC) {
                fprintf(stderr, "%s: %s: Illegal vector name.\n",
                cmp->fname, name);
                return(ERRR);
            }
            table[i] = Ft_install(name, UNDEFVEC, Ft_Samples);
        }
        else if (table[i]->type != VEC && table[i]->type != UNDEFVEC) {
            fprintf(stderr, "%s: %s: Not a vector.\n",
            cmp->fname, table[i]->name);
            return(ERRR);
        }
        if ((sc = strstr(argv[i+2], "{")) != 0) {
            char *eh;
            char low[TOKENSIZE+1];
            char high[TOKENSIZE+1];

            if (strstr(argv[i+2], "}") == 0) {
                fprintf(stderr, "%s: %s: Unmatched brace.\n",
                cmp->fname, argv[i+2]);
                return(ERRR);
            }
            if (sscanf(sc, "{%[^:]:%[^}]", low, high) != 2) {
                fprintf(stderr, "%s: Line range misconstruction at: %s.\n",
                cmp->fname, sc);
                return(usage(cmp));
            }
            if (strcmp(low, "*") == 0) {
                lines[0] = 0;
            }
            else {
                lines[0] = (int) strtod(low, &eh);
#ifndef SUN3
                if (*eh != '\0') {
#else
                if (*--eh != '\0') {  /* SUN OS3.5 strtod brain dead */
#endif
                    fprintf(stderr,
                    "%s: Low line range misconstruction at: %s.\n",
                    cmp->fname, sc);
                    return(usage(cmp));
                }
            }
            if (strcmp(high, "*") == 0) {
                lines[1] = Ft_Samples + 32;
            }
            else {
                lines[1] = (int) strtod(high, &eh);
#ifndef SUN3
                if (*eh != '\0') {
#else
                if (*--eh != '\0') {  /* SUN OS3.5 strtod brain dead */
#endif
                    fprintf(stderr,
                    "%s: High range line misconstruction at: %s.\n",
                    cmp->fname, sc);
                    return(usage(cmp));
                }
            }
        }
        if ((sc = strstr(argv[i+2], "[")) != 0) {
            char *eh;
            char low[TOKENSIZE+1];
            char high[TOKENSIZE+1];

            if (strstr(argv[i+2], "]") == 0) {
                fprintf(stderr, "%s: %s: Unmatched bracket.\n",
                cmp->fname, argv[i+2]);
                return(ERRR);
            }
            if (sscanf(sc, "[%[^:]:%[^]]", low, high) != 2) {
                fprintf(stderr, "%s: Range misconstruction at: %s.\n",
                cmp->fname, sc);
                return(usage(cmp));
            }
            if (strcmp(low, "*") == 0) {
                irange[0][i] = 0;
            }
            else {
                irange[0][i] = 1;
                range[0][i] = strtod(low, &eh);
#ifndef SUN3
                if (*eh != '\0') {
#else
                if (*--eh != '\0') {  /* SUN OS3.5 strtod brain dead */
#endif
                    fprintf(stderr, "%s: Low range misconstruction at: %s.\n",
                    cmp->fname, sc);
                    return(usage(cmp));
                }
            }
            if (strcmp(high, "*") == 0) {
                irange[1][i] = 0;
            }
            else {
                irange[1][i] = 1;
                range[1][i] = strtod(high, &eh);
#ifndef SUN
                if (*eh != '\0') {
#else
                if (*--eh != '\0') {  /* SUN OS3.5 strtod brain dead */
#endif
                    fprintf(stderr, "%s: High range misconstruction at: %s.\n",
                    cmp->fname, sc);
                    return(usage(cmp));
                }
            }
        }
        else {
            irange[0][i] = irange[1][i] = 0;
        }
    }
    return(Ft_readvar(argv, table, loctable, irange, range, lines, argc-2, exec,
    cmp->fname));
}

static int do_svvec(int argc, char **argv, char *mode, Command *cmp)
{
    FILE *fp = stdout;
    int i, j;
    Symbol *table[MAXVAR];
    extern Symbol *Ft_lookup(char *);

    if ((int) *Ft_Data == 0) {
        fprintf(stderr, "%s: No data!\n", cmp->fname);
        return(ERRR);
    }
    if (argc > MAXVAR) {
        fprintf(stderr, "%s: %d: Too many vectors.\n", cmp->fname, argc);
        return(ERRR);
    }
    if (*mode != 's') argc--;
    if (argc < 3)
        return(usage(cmp));
    for (i=0;i<argc-2;i++) {
        if ((table[i] = Ft_lookup(argv[i+2])) == 0) {
            fprintf(stderr, "%s: %s: Unknown vector.\n",
            cmp->fname, argv[i+2]);
            return(ERRR);
        }
        if (table[i]->type != VEC) {
            fprintf(stderr, "%s: %s: Not a vector.\n",
            cmp->fname, table[i]->name);
            return(ERRR);
        }
    }
    switch (*mode) {
        case 'w':
        case 'a':
            if ((fp = fopen(argv[argc], mode)) == 0) {
                fprintf(stderr, "%s: %s: Permission denied.\n",
                cmp->fname, argv[argc]);
                return(ERRR);
            }
            /********
            fputc(Ft_Comchar, fp);
            for (j=0;j<argc-2;j++) {
                fprintf(fp, "\t%s", table[j]->name);
            }
            fputc('\n', fp);
            ********/
            for (i=1;i<= (int) *Ft_Data;i++) {
                fprintf(fp, Ft_Format, table[0]->u.vec[i]);
                for (j=1;j<argc-2;j++) {
                    fprintf(fp, Ft_TFormat, table[j]->u.vec[i]);
                }
                fputc('\n', fp);
            }
            fclose(fp);
            break;
        case 's':
            if ((int) *Ft_Data > 24 && Ft_Interact && *Ft_Pager) {
                if ((fp = popen(Ft_Pager, "w")) == (FILE *)NULL)  {
                    fprintf(stderr, "Warning: %s: Could not open pager %s.\n",
                    cmp->fname, Ft_Pager);
                    fp = stdout;
                }
            }
            for (i=1;i<=(int) *Ft_Data;i++) {
                if (fprintf(fp, " %4d:", i) < 0)
                    break;
                for (j=0;j<argc-2;j++) {
                    fprintf(fp, Ft_TFormat, table[j]->u.vec[i]);
                }
                if (fputc('\n', fp) < 0)
                    break;
            }
            if (fp != stdout) {
				fflush(fp);
				pclose(fp);
			}
            break;
        default:
            fprintf(stderr, "%s: Impossible printing mode.\n",
            cmp->fname);
            Ft_catcher(ERRR);
    }
    return(0);
}

/*
typedef union {
    double db;
    char* str;
    } Vardesc;
*/

static int do_svvar(int argc, char **argv, char *mode, Command *cmp)
{
    FILE *fp = stdout;
    int j;
    Vardesc vvec[MAXVAR];
    int astring[MAXVAR];

    if (*mode != 's')
        argc--;
    if (argc < 3)
        return(usage(cmp));
    if (argc-2 > MAXVAR) {
        fprintf(stderr, "%s: %d: Too many variables.\n",
        cmp->fname, argc-2);
        return(ERRR);
    }
    if (splitvar(2, argc, argv, vvec, astring, cmp) == ERRR)
        return(ERRR);

    switch(*mode) {
        case 'w':
        case 'a':
            if ((fp = fopen(argv[argc], mode)) == 0) {
                fprintf(stderr, "%s: %s: Permission denied.\n",
                cmp->fname, argv[argc]);
                return(ERRR);
            }
            if (astring[0]) {
                   fputs(vvec[0].str, fp);
            }
            else {
                   fprintf(fp, Ft_Format, vvec[0].db);
            }
            for (j=1;j<argc-2;j++) {
                if (astring[j]) {
                    fprintf(fp, "\t%s", vvec[j].str);
                }
                else {
                    fprintf(fp, Ft_TFormat, vvec[j].db);
                }
            }
            fputc('\n', fp);
            fclose(fp);
            break;
        case 's':
            for (j=0;j<argc-2;j++) {
                if (astring[j]) {
                    fprintf(fp, "\t%s", vvec[j].str);
                }
                else {
                    fprintf(fp, Ft_TFormat, vvec[j].db);
                }
            }
            fputc('\n', fp);
            break;
        default:
            fprintf(stderr, "%s: Impossible printing mode.\n", cmp->fname);
            Ft_catcher(ERRR);
    }
    return(0);
}

static int splitvar(int ifrom, int xto, char **argv, Vardesc *dbvec, int *astringvec, Command *cmp)
{
    register int i, j;
    char *cp;
    int index;
    Symbol *sym;
    char name[TOKENSIZE+4];
    extern Symbol *Ft_lookup(char *);

    for (i=0, j=ifrom; j<xto; i++, j++) {
        sscanf(argv[j], "%[^[]", name);
        index = 0;
        if ((sym = Ft_lookup(name)) == 0) {
            fprintf(stderr, "%s: %s: Unknown variable.\n", cmp->fname, name);
            return(ERRR);
        }
        astringvec[i] = 0;  /* assume they all are numbers */
        switch(sym->type) {
            case BLTINSTRVAR:
            case BLTINSTRCONST:
            case STRVAR:
            case STRCONST:
                astringvec[i] = 1;
                dbvec[i].str = sym->u.str;
                break;
            case BLTINVAR:
            case BLTINCONST:
            case VAR:
            case CONST:
                dbvec[i].db = sym->u.val;
                break;
            case PARAM:
                if ((int) *Ft_Param == 0) {
                    fprintf(stderr, "%s: %s: Null size vector!\n",
                    cmp->fname, name);
                    return(ERRR);
                }
                if ((cp = strstr(argv[j], "[")) != NULL) {
                    if (sscanf(cp+1, "%d]", &index) != 1) {
                        fprintf(stderr,
                        "%s: %s: Badly formed vector element.\n",
                        cmp->fname, argv[j]);
                        return(ERRR);
                    }
                }
                if (index < 1 || (int) *Ft_Param < index) {
                    fprintf(stderr, "%s: %s: Illegal parameter index.\n",
                    cmp->fname, name);
                    return(ERRR);
                }
                dbvec[i].db = sym->u.vec[index];
                break;
            case VEC:
                if ((int) *Ft_Data == 0) {
                    fprintf(stderr, "%s: %s: Null size vector!\n",
                    cmp->fname, name);
                    return(ERRR);
                }
                if ((cp = strstr(argv[j], "[")) != NULL) {
                    if (sscanf(cp+1, "%d]", &index) != 1) {
                        fprintf(stderr,
                        "%s: %s: Badly formed vector element.\n",
                        cmp->fname, argv[j]);
                        return(ERRR);
                    }
                }
                if (index < 1 || (int) *Ft_Data < index) {
                    fprintf(stderr, "%s: %s: Illegal vector index.\n",
                    cmp->fname, name);
                    return(ERRR);
                }
                dbvec[i].db = sym->u.vec[index];
                break;
            default:
                fprintf(stderr, "%s: %s: Not a printable variable.\n",
                cmp->fname, sym->name);
                return(ERRR);
        }
    }
    return(i);
}

static int do_svpar(int argc, char **argv, char *mode, Command *cmp)
{
    int j;
    FILE *fp = stdout;
    Vardesc vvec[MAXVAR];
    int astring[MAXVAR];
    extern char Ft_Pname[];

    if ((int) *Ft_Param == 0) {
        fprintf(stderr, "%s: No parameters!\n", cmp->fname);
        return(ERRR);
    }
    if (*mode != 's')
        argc--;
    if (argc < 2)
        return(usage(cmp));
    if (argc-2 > MAXVAR) {
        fprintf(stderr, "%s: %d: Too many variables.\n",
        cmp->fname, argc-2);
        return(ERRR);
    }
    if (argc > 2) {
        if (splitvar(2, argc, argv, vvec, astring, cmp) == ERRR)
            return(ERRR);
    }
    switch (*mode) {
        case 'w':
        case 'a':
        if ((fp = fopen(argv[argc], mode)) == 0) {
            fprintf(stderr, "%s: %s: Permission denied.\n",
            cmp->fname, argv[argc]);
            return(ERRR);
        }
        if (argc > 2) {
            if (astring[0]) {
                fputs(vvec[0].str, fp);
            }
            else {
                fprintf(fp, Ft_Format, vvec[0].db);
            }
            for (j=1;j<argc-2;j++) {
                if (astring[j]) {
                       fprintf(fp, "\t%s", vvec[j].str);
                }
                else {
                       fprintf(fp, Ft_TFormat, vvec[j].db);
                }
            }
            fputc('\t', fp);
        }
        fprintf(fp, Ft_Format, Ft_A[1]);
        fprintf(fp, Ft_TFormat, Ft_DA[1]);
        for (j=2;j<=(int) *Ft_Param;j++) {
            fprintf(fp, Ft_TFormat, Ft_A[j]);
            fprintf(fp, Ft_TFormat, Ft_DA[j]);
        }
        fputc('\n', fp);
        fclose(fp);
        break;
        case 's':
        if ((int) *Ft_Param > 24 && Ft_Interact && *Ft_Pager) {
            if ((fp = popen(Ft_Pager, "w")) == (FILE *)NULL)  {
                fprintf(stderr, "Warning: %s: Could not open pager %s.\n",
                cmp->fname, Ft_Pager);
                fp = stdout;
            }
        }
        if (argc > 2) {
            if (astring[0]) {
                fputs(vvec[0].str, fp);
            }
            else {
                fprintf(fp, Ft_Format, vvec[0].db);
            }
            for (j=1;j<argc-2;j++) {
                if (astring[j]) {
                       fprintf(fp, "\t%s", vvec[j].str);
                }
                else {
                       fprintf(fp, Ft_TFormat, vvec[j].db);
                }
            }
            fputc('\n', fp);
        }
        for (j=1;j <= (int) *Ft_Param;j++) {
            fprintf(fp, " %s[%d]:", Ft_Pname, j);
            fprintf(fp, Ft_TFormat, Ft_A[j]);
            fprintf(fp, " +/- ");
            fprintf(fp, Ft_TFormat, Ft_DA[j]);
            fputc('\n', fp);
        }
        if (fp != stdout) {
			fflush(fp);
			pclose(fp);
		}
        break;
        default:
        fprintf(stderr, "%s: Impossible printing mode.\n", cmp->fname);
        Ft_catcher(ERRR);
    }
    return(0);
}

#include <setjmp.h>
/* CMODE FUNCTION */
static int do_cmode(int argc, char **argv, char *l, Command *cmp)
{
    extern jmp_buf Ft_Jump;
    extern FILE *Ft_Outprint;
    int val;

    if (argc != 1)  /* send to let if some command  */
        return(let(argc, argv, l, cmp));
    if (Ft_Interact && !Ft_iolevel()) {
        fputs("\tUse `fmode' or ^D to come back...\n", stderr);
        setjmp(Ft_Jump);
    }
    Ft_Mode = CMODE;
    for(Ft_initcode(); (val = Ft_more_input(0, 0));Ft_initcode()) {
        if (val == ERRR)
            continue;
        Ft_mathyyparse();
    }
    fflush(Ft_Outprint);
    return(0);
}   

/* DO_DUMPLOT FUNCTION  */
static int do_dumplot(int argc, char **argv, char *l, Command *cmp)
{
    int i;
    Symbol *sym;
    double *dblv[MAXDARG];
    extern Symbol *Ft_lookup(char *);

    if ((int) *Ft_Data == 0) {
        fprintf(stderr, "%s: No data!\n", cmp->fname);
        return(ERRR);
    }

    if (argc < 2 || MAXDARG < argc) {
        fprintf(stderr, "%s: %d: Unsupported number of argument.\n",
        cmp->fname, argc);
        return(ERRR);
    }
    for (i=0;i<argc-1;i++) {
        if ((sym = Ft_lookup(argv[i+1])) == 0) {
            fprintf(stderr, "%s: %s: Unknown vector.\n",
            cmp->fname, argv[i+1]);
            return(ERRR);
        }
        if (sym->type != VEC) {
            fprintf(stderr, "%s: %s: Not a vector.\n",
            cmp->fname, sym->name);
            return(ERRR);
        }
        dblv[i] = sym->u.vec;
    }
    dblv[i] = 0;
    return(Ft_dumplot(dblv, (int) *Ft_Data));
}

/* DO_DEFINE FUNCTION */
static int do_defmac(int argc, char **argv, char *l, Command *cmp)
{
    Macro *mac;
    char *cp;

    if (argc != 3)
        return(usage(cmp));

    if (Ft_almost(argv[1], "m!acro") || Ft_almost(argv[1], "u!nmacro")) {
        fprintf(stderr, "%s: %s: Too dangerous to define that!\n",
        cmp->fname, argv[1]);
        return(ERRR);
    }
    if ((mac = Ft_maclook(argv[1], ANALIAS)) != NULL) {
        fprintf(stderr, "%s: %s: Name conflict with existing alias.\n",
        cmp->fname, argv[1]);
        return(ERRR);
    }
    if ((cp = Ft_readmacro("macro? ")) == NULL) {
        return(ERRR);
    }
    if ((mac = Ft_maclook(argv[1], AMACRO)) != NULL) {
        if (Ft_macremove(argv[1], AMACRO) == ERRR) {
            return(ERRR);
        }
    }
    if ((mac = Ft_macinstall(argv[1], cp, AMACRO)) == NULL) {
        return(ERRR);
    }
    mac->nargs = atoi(argv[2]);
    return(0);
}

/* DO_UNDEFINE FUNCTION */
static int do_udefmac(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc < 2)
        return(usage(cmp));
    for (i=1;i<argc;i++) {
        Ft_macremove(argv[i], AMACRO);
    }
    return(0);
}

/* DO_WHILE FUNCTION */
static int do_while(int argc, char **argv, char *line, Command *cmp)
{
    char condition[TOKENSIZE+16];
    extern double *Ft_If_value;
    Macro *lmac;
    int liolevel;
    int ivalue;
    char *cp;
    char macroname[MAXMACRO];
    extern int Ft_Dolevel;
    extern char *Ft_read_loop(char **argv, char *fprom);

    if (argc < 2 || argv[1][0] != '(')
        return(usage(cmp));
    
    sprintf(condition, "if_value = %s\n", argv[1]);
    if (let(0, argv, condition, 0) == ERRR)
        return(ERRR);
    sprintf(macroname, "while_loop%d", Ft_Dolevel+1);
    if ((lmac = Ft_maclook(macroname, AMACRO)) != NULL) {
           if (Ft_macremove(macroname, AMACRO) == ERRR) {
               return(ERRR);
           }
    }
    if (argc > 2) {
        cp = line + strlen(argv[0]) + strlen(argv[1]) + 2;
    }
    else if ((cp = Ft_read_loop(argv, "while")) == NULL) {
           return(ERRR);
    }
    if ((lmac = Ft_macinstall(macroname, cp, AMACRO)) == NULL) {
        return(ERRR);
    }
    lmac->nargs = 0;
    liolevel = Ft_iolevel();
    Ft_Dolevel++;
    ivalue = (int) *Ft_If_value;
    while (ivalue) {
        if (macrun(lmac, liolevel) == ERRR) {
            Ft_Dolevel--;
            return(ERRR);
        }
        if (let(0, argv, condition, 0) == ERRR) {
            Ft_Dolevel--;
            return(ERRR);
        }
        ivalue = (int) *Ft_If_value;
    }
    Ft_Dolevel--;
    return(0);
}

/* DO_FOREACH FUNCTION */
static int do_foreach(int argc, char **argv, char *line, Command *cmp)
{
    Macro *lmac;
    Symbol *lvar;
    FILE *pfp;
    int liolevel;
	int looploop, i, c;
    char *cp;
    char macroname[MAXMACRO];
    char commandline[LINESIZE+4];
    extern int Ft_Dolevel;
    extern char *Ft_read_loop(char **argv, char *fprom);

    if (argc < 4)
        return(usage(cmp));
    if (!Ft_almost(argv[2], "in"))
        return(usage(cmp));
    if (Ft_varcpy(0, argv[1]) != STRVAR) {
        fprintf(stderr, "foreach: %s: Not a legal string name.\n", argv[1]);
        return(ERRR);
    }
    if ((lvar = Ft_lookup(argv[1])) != NULL) {
        if (Ft_symremove(argv[1], 1)) {
            return(ERRR);
        }
    }
    lvar = Ft_install(argv[1], STRVAR, TOKENSIZE+4);
    cp = line + strlen(argv[0]) + strlen(argv[1]) + strlen(argv[2]) + 3;
    sprintf(commandline, "%s", cp);
    sprintf(macroname, "foreach_loop%d", Ft_Dolevel+1);
    if ((lmac = Ft_maclook(macroname, AMACRO)) != NULL) {
        if (Ft_macremove(macroname, AMACRO) == ERRR) {
            return(ERRR);
        }
    }
    if ((cp = Ft_read_loop(argv, "foreach")) == NULL) {
        return(ERRR);
    }
    if ((lmac = Ft_macinstall(macroname, cp, AMACRO)) == NULL) {
        return(ERRR);
    }
    lmac->nargs = 0;

    if ((pfp = popen(commandline, "r")) == (FILE *)NULL) {
		commandline[strlen(commandline)-1] = '\0';
        fprintf(stderr, "%s: Could not open `%s' process.\n",
        cmp->fname, commandline);
        return(ERRR);
    }
    liolevel = Ft_iolevel();
    Ft_Dolevel++;
	looploop = 0;
	cp = lvar->u.str;
    while (1) {
		i = 0;
		while ((c = fgetc(pfp)) >= 0 && isspace(c) ) { /* swallow space */
			;
		}
		if (c < 0 ) {		/* EOF ? */
			break;
		}
		cp[i++] = c;
		/* read the token */
		while ((c = fgetc(pfp)) >= 0 && !isspace(c) && i < LINESIZE) {
			cp[i++] = c;
		}
		if (i >= LINESIZE) {
			fprintf(stderr, "Warning: %s: String %d is too long.\n",
			cmp->fname, ++looploop);
			continue;
		}
		cp[i] = 0;
		if (i == 0)
			break;
        if (macrun(lmac, liolevel) == ERRR) {
            fflush(pfp);
			pclose(pfp);
            Ft_Dolevel--;
            return(ERRR);
        }
		looploop++;
    }
    fflush(pfp);
	pclose(pfp);
    Ft_Dolevel--;
	if (looploop == 0) {
		commandline[strlen(commandline)-1] = '\0';
        fprintf(stderr, "Warning: %s: Command `%s' is an empty loop.\n",
        cmp->fname, commandline);
    }
    return(0);
}

static int macrun(Macro *mac, int level)
{
    char *cp;
    int eof;
    extern char *Ft_nextline(char *, int *);

    Ft_pushio(mac->line, AMACRO, mac->name);
    while (Ft_iolevel() > level) {
        if ((cp = Ft_nextline(Ft_Prompt_fm, &eof)) == NULL) {
            continue;
        }
        if (Ft_processline(cp) == ERRR) {
            return(ERRR);
        }
    }
    return(0);
}

static int do_alias(int argc, char **argv, char *line, Command *cmp)
{
    Macro *mac;
    char *cp;

    switch (argc) {
    case 1:
        return(Ft_showmac(2, argv, ANALIAS));
    case 2:   
        if ((mac = Ft_maclook(argv[1], ANALIAS)) != NULL) {
            fputs(mac->line, stdout);
        }
        return(0);
    default:   
        if (Ft_almost(argv[1], "al!ias") || Ft_almost(argv[1], "una!lias")) {
            fprintf(stderr, "%s: %s: Too dangerous to alias that!\n",
            argv[1], cmp->fname);
            return(ERRR);
        }
        if (*argv[1] == '&') {
            fprintf(stderr,
            "%s: %s: Not allowed to start an alias with `&'!\n",
            argv[1], cmp->fname);
            return(ERRR);
        }
        if (Ft_almost(argv[2], argv[1])) {
            fprintf(stderr, "%s: %s: Circular alias.\n",
            cmp->fname, argv[1]);
            return(ERRR);
        }
        if ((mac = Ft_maclook(argv[1], AMACRO)) != NULL) {
            fprintf(stderr, "%s: %s: Name conflict with existing macro.\n",
            cmp->fname, argv[1]);
            return(ERRR);
        }
        if ((mac = Ft_maclook(argv[1], ANALIAS)) != NULL) {
            if (Ft_macremove(argv[1], ANALIAS) == ERRR) {
                return(ERRR);
            }
        }
        cp = line + strlen(argv[0]) + strlen(argv[1]) + 2;
        if ((mac = Ft_macinstall(argv[1], cp, ANALIAS)) == NULL) {
            return(ERRR);
        }
        mac->nargs = 0;
        return(0);
    }
}

static int do_unalias(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc < 2)
        return(usage(cmp));
    for (i=1;i<argc;i++) {
        Ft_macremove(argv[i], ANALIAS);
    }
    return(0);
}

static int do_lock(int argc, char **argv, char *l, Command *cmp)
{
    int i, j;

    if (argc < 2)
        return(usage(cmp));
    for (j=0, i=1;i<argc;i++) {
        j += Ft_lock(1, argv[i], cmp->fname);
    }
    if (j)
        return(ERRR);
    return(0);
}

static int do_unlock(int argc, char **argv, char *l, Command *cmp)
{
    int i;

    if (argc < 2)
        return(usage(cmp));
    for (i=1;i<argc;i++) {
        Ft_lock(0, argv[i], cmp->fname);
    }
    return(0);
}

static int usage(Command *cmd)
{
    fprintf(stderr, "Usage: `%s' %s\n", cmd->fname, cmd->usage);
    return(ERRR);
}

static int do_stexp(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    Ft_Expandhist = 1;
    return(0);
}

static int do_stnexp(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    Ft_Expandhist = 0;
    return(0);
}
   
static int do_shexp(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%s\n", (Ft_Expandhist == 1? "on": "off") );
    return(0);
}

static int do_smooth(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 4)
        return(usage(cmp));
    return(Ft_run_smooth(argc, argv, (int) *Ft_Data));
}

static int do_fft(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 5)
        return(usage(cmp));
    return(Ft_run_fft(argc, argv, 1, (int) *Ft_Data));
}

static int do_invfft(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 5)
        return(usage(cmp));
    return(Ft_run_fft(argc, argv, -1, (int) *Ft_Data));
}

static int do_stpromptfm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    strncpy(Ft_Prompt_fm, argv[2], MAXPROMPT);
    Ft_Prompt_fm[MAXPROMPT] = '\0';
    return(0);
}

static int do_stpromptcm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    strncpy(Ft_Prompt_cm, argv[2], MAXPROMPT);
    Ft_Prompt_cm[MAXPROMPT] = '\0';
    return(0);
}

static int do_stpromptpm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 3)
        return(usage(cmp));
    strncpy(Ft_Prompt_pm, argv[2], MAXPROMPT);
    Ft_Prompt_pm[MAXPROMPT] = '\0';
    return(0);
}

static int do_shpromptpm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fputs(Ft_Prompt_pm, stderr);
    return(0);
}

static int do_shpromptcm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fputs(Ft_Prompt_cm, stderr);
    return(0);
}

static int do_shpromptfm(int argc, char **argv, char *l, Command *cmp)
{
    if (argc != 2)
        return(usage(cmp));
    fputs(Ft_Prompt_fm, stderr);
    return(0);
}

static int do_sterr(int argc, char **argv, char *l, Command *cmp)
{
    if (argc == 2 || argv[2][0] == '?') {
        fputs("Error check levels:\n", stderr);
        fputs("\t 0: Clear check bits.\n", stderr);
        fputs("\t 1: Check for `infinity' values.\n", stderr);
        fputs("\t 2: Check for `not a number' values.\n", stderr);
        fputs("\t 3: Check for `out of domain' math function errors.\n",
        stderr);
        fputs("\t 4: Check for `out of range' math function errors.\n",
        stderr);
    }
    else {
         int chk, i;
        float flchk;

        for (i=2;i<argc;i++) {
            if (sscanf(argv[i], "%f", &flchk) != 1) {
                fprintf(stderr, "%s: Could not read number \"%s\".\n",
                cmp->fname, argv[i]);
                return(ERRR);
            }
            chk = (int)flchk;
            if (chk)
                Ft_Check |= 01<<(chk-1);
            else
                Ft_Check = 0;
        }
    }
    return(0);
}

static int do_sherr(int argc, char **argv, char *l, Command *cmp)
{
    extern int Ft_Check;

    if (argc != 2)
        return(usage(cmp));
    fprintf(stderr, "%o\n", Ft_Check);
    return(0);
}

static int do_if(int argc, char **argv, char *line, Command *cmp)
{
    char condition[TOKENSIZE+16];
    extern double *Ft_If_value;
    int elseif;
    int ivalue;

    elseif = Ft_almost(cmp->fname, "else");  /* who called me? */
    if (argc < 3 || argv[1][0] != '(') {
        if (!elseif) {
            return(usage(cmp));
        }
        else {
            fputs("if: Bad 'else if' construction.\n", stderr);
            return(ERRR);
        }
    }
    sprintf(condition, "if_value = %s\n", argv[1]);
    if (let(0, argv, condition, 0) == ERRR)
        return(ERRR);
    ivalue = (int) *Ft_If_value;
    if (!ivalue) { /* FALSE */
        if (Ft_almost(argv[2], "th!en")) {
            if (elseif) {
                return(Ft_switchif(FALSE_IF));
            }
            else {
                return(Ft_pushif(FALSE_IF));
            }
        }
    }
    if (elseif) {     /* TRUE */
        if (Ft_switchif(TRUE_IF) == ERRR)
            return(ERRR);
        return(0);
    }
    if (!Ft_almost(argv[2], "th!en")) {
        char *cp;

        cp = line + strlen(argv[0]) + strlen(argv[1]) + 2;
        return(Ft_command(argc-2, argv+2, cp));
    }
    return(Ft_pushif(TRUE_IF));
}

static int do_else(int argc, char **argv, char *line, Command *cmp)
{
    if (argc == 1)
        return(Ft_switchif(FORCED_IF));
    if (Ft_almost(argv[1], "if")) {
        char *cp;

        cp = line + strlen(argv[0]) + 1;
        return(do_if(argc-1, argv+1, cp, cmp));
    }
    return(usage(cmp));
}

static int do_endif(int argc, char **argv, char *line, Command *cmp)
{
    if (argc != 1)
        return(usage(cmp));
    return(Ft_popif());
}

static int do_parse(int argc, char **argv, char *line, Command *cmp)
{
    int i;

    fprintf(stderr, "line: %s", line);
    for (i=0; i< argc;i++)
        fprintf(stderr, "argv[%d]: %s\n", i, argv[i]);
    return(0);
}

static int do_spline(int argc, char **argv, char *line, Command *cmp)
{
    double dy1, dyn;
    double *vec1, *vec2;
    Symbol *sym;
    extern Symbol *Ft_lookup(char *);

    if (3 > argc || argc > 5)
        return(usage(cmp));

    dyn = dy1 = 1.0e30; /* natural by default */
    switch (argc) {
        case 5:
        if (strcmp(argv[5], "*") != 0 && sscanf(argv[4], "%lf", &dyn) != 1) {
            fprintf(stderr,
            "%s: Could not read number from argument 5.\n", cmp->fname);
            return(ERRR);
        }
        case 4:
        if (strcmp(argv[4], "*") != 0 && sscanf(argv[3], "%lf", &dy1) != 1) {
            fprintf(stderr,
            "%s: Could not read number from argument 4.\n", cmp->fname);
            return(ERRR);
        }
        case 3:
        break;
    }
    if ((sym = Ft_lookup(argv[1])) == NULL || sym->type != VEC) {
        fprintf(stderr, "%s: %s: No such vector.\n", cmp->fname, argv[1]);
        return(ERRR);
    }
    vec1 = sym->u.vec;
    if ((sym = Ft_lookup(argv[2])) == NULL || sym->type != VEC) {
        fprintf(stderr, "%s: %s: No such vector.\n", cmp->fname, argv[2]);
        return(ERRR);
    }
    vec2 = sym->u.vec;
    return(Ft_spline(vec1, vec2, dy1, dyn, (int) *Ft_Data));
}

static void signal_on(void)
{
    signal(SIGINT, Ft_catcher);
    signal(SIGHUP, Ft_catcher);
    signal(SIGTSTP, Ft_catcher);
}

static void signal_off(void)
{
    signal(SIGINT, SIG_DFL);
    signal(SIGHUP, SIG_DFL);
    signal(SIGTSTP, SIG_DFL);
}

/* #if defined(sgi) || defined(sparc) || defined(sun) */
#ifdef DL_YES
/* The module for dynamic loading */
#include "install.c"
#else  /* AIX or HP-UX */
#include "install.dummy.c"
#endif
