/*
 * calc - arbitrary precision calculator
 *
 * Copyright (C) 1999-2013,2021-2023  David I. Bell, Landon Curt Noll and Ernest Bowen
 *
 * Calc is open software; you can redistribute it and/or modify it under
 * the terms of the version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * Calc is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
 * Public License for more details.
 *
 * A copy of version 2.1 of the GNU Lesser General Public License is
 * distributed with calc under the filename COPYING-LGPL.  You should have
 * received a copy with calc; if not, write to Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Under source code control:   1990/02/15 01:48:11
 * File existed as early as:    before 1990
 *
 * Share and enjoy!  :-)        http://www.isthe.com/chongo/tech/comp/calc/
 */

#include <stdio.h>
#include <signal.h>

#if !defined(_WIN32) && !defined(_WIN64)
# include <pwd.h>
#endif

#include <sys/types.h>
#include <ctype.h>

#if defined(_WIN32) || defined(_WIN64)
# include <io.h>
# if !defined(NOTCYGWIN)
/*
 * getopt.h file is from the Cygwin GNU library
 *
 * See:
 *      http://sources.redhat.com/cygwin/
 */
# include "../getopt/getopt.h"
# endif
# define strdup _strdup
# define isatty _isatty
#endif /* Windows */

#define CALC_C
#include "calc.h"
#include "hist.h"
#include "func.h"
#include "opcodes.h"
#include "conf.h"
#include "token.h"
#include "symbol.h"
#include "have_uid_t.h"
#include "have_const.h"
#include "custom.h"
#include "lib_calc.h"
#include "args.h"
#include "zmath.h"
#include "strl.h"

#include "have_unistd.h"
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif

#include "have_stdlib.h"
#if defined(HAVE_STDLIB_H)
#include <stdlib.h>
#endif

#include "have_strdup.h"
#if !defined(HAVE_STRDUP)
# define strdup(x) calc_strdup((CONST char *)(x))
#endif /* HAVE_STRDUP */

#include "have_unused.h"


#include "errtbl.h"
#include "banned.h"     /* include after system header <> includes */


/*
 * S_FUNC definitions and functions
 */
S_FUNC void intint(int arg);    /* interrupt routine */
S_FUNC void calc_interrupt(char *fmt, ...);
S_FUNC int nextcp(char **cpp, int *ip, int argc, char **argv, bool haveendstr);
S_FUNC void set_run_state(run state);

/*
 * Top level calculator routine.
 */
int
main(int argc, char **argv)
{
        int want_defhelp = 0;   /* 1=> we only want the default help */
        int cmdlen;             /* length of the command string */
        int newcmdlen;
        int c;                  /* option */
        int index;
        int maxindex;
        char *cp;
        char *endcp;
        char *bp;
        bool done = false;
        bool havearg;
        bool haveendstr;
        bool stdin_closed = false;
        size_t len;

        /*
         * parse args
         */
        program = argv[0];
        script_name = strdup(argv[0]);
        if (script_name == NULL) {
                fprintf(stderr, "%s: failed to strdup(argv[0])\n", program);
                exit(1);
        }

        cmdbuf[0] = '\0';
        cmdlen = 0;

        /* process command line options */

        index = 1;
        cp = endcp = NULL;
        maxindex = argc;
        havecommands = false;
        while (index < maxindex && !done) {
                cp = argv[index];
                if (*cp == '\0') {
                        index++;
                        continue;
                }
                for (;;) {
                        havearg = false;
                        if (*cp != '-') {
                                done = true;
                                break;
                        }
                        ++cp;
                        if (*cp == '-') {
                                cp++;
                                while (*cp == ' ')
                                        ++cp;
                                done = true;
                                break;
                        }

                        for (;;) {
                                c = *cp;
                                if (c == '\0' || c == ' ')
                                        break;
                                switch (c) {
                                case 'C':
#if defined(CUSTOM)

                                        /*
                                         * error if libcustcalc was compiled with CUSTOM undefined
                                         */
                                        if (custom_compiled() != true) {
                                            math_error("%s: calc was built with custom functions enabled, "
                                                       "custom_compiled() returned: %d != %d",
                                                       program, custom_compiled(), true);
                                            exit(1);
                                        }

                                        /*
                                         * indicate that custom functions are now allowed
                                         */
                                        allow_custom = true;
                                        break;
#else /* CUSTOM */

                                        /*
                                         * error if libcustcalc was compiled with CUSTOM defined
                                         */
                                        if (custom_compiled() != false) {
                                            math_error("%s: calc was built with custom functions disabled, "
                                                       "custom_compiled() returned: %d != %d",
                                                       program, custom_compiled(), false);
                                        }

                                        /*
                                         * we are too early in processing to
                                         * call libcalc_call_me_last() -
                                         * nothing to cleanup
                                         */
                                        fprintf(stderr,
                                            "%s: calc was built with custom"
                                            " functions disabled, -C usage is"
                                            " disallowed\n", program);
                                        exit(1);
#endif /* CUSTOM */
                                case 'e':
                                        no_env = true;
                                        break;
                                case 'h':
                                        want_defhelp = 1;
                                        break;
                                case 'i':
                                        i_flag = true;
                                        break;
                                case 'm':
                                        cp++;
                                        while (*cp == ' ' || *cp == '\t')
                                                cp++;
                                        if (*cp == '\0') {
                                                index++;
                                                if (index >= argc) {
                                                        fprintf(stderr,
                                                                "-m expects"
                                                                " argument");
                                                        exit(2);
                                                }
                                                cp = argv[index];
                                        }

                                        if (*cp < '0' || *cp > '7') {
                                                /*
                                                 * we are too early in
                                                 * processing to call
                                                 * libcalc_call_me_last()
                                                 * nothing to cleanup
                                                 */
                                                fprintf(stderr,
                                                        "%s: unknown -m arg\n",
                                                        program);
                                                exit(3);
                                        }
                                        allow_read = (((*cp-'0') & 04) > 0);
                                        allow_write = (((*cp-'0') & 02) > 0);
                                        allow_exec = (((*cp-'0') & 01) > 0);
                                        cp++;
                                        if (*cp != ' ' && *cp != '\0') {
                                                fprintf(stderr, "??? m-arg");
                                                exit(4);
                                        }
                                        havearg = true;
                                        break;
                                case 'n':
                                        /*
                                         * -n is deprecated and may be reused
                                         * for another purpose in the future
                                         */
                                        break;
                                case 'O':
                                        use_old_std = true;
                                        break;
                                case 'p':
                                        p_flag = true;
                                        break;
                                case 'q':
                                        q_flag = true;
                                        break;
                                case 'u':
                                        u_flag = true;
                                        break;
                                case 'c':
                                        c_flag = true;
                                        break;
                                case 'd':
                                        d_flag = true;
                                        break;
                                case 'v':
                                        /*
                                         * we are too early in processing to
                                         * call libcalc_call_me_last() -
                                         * nothing to cleanup
                                         */
                                        fputs(CALC_TITLE, stdout);
#if defined(CUSTOM)
                                        fputs(" w/custom functions", stdout);
#else
                                        fputs(" w/o custom functions", stdout);
#endif /* CUSTOM */
                                        printf(" (version %s)\n", version());
                                        exit(0);
                                case 'D':
                                        /*
                                         * parse the -D arg
                                         *
                                         * Could be:
                                         *
                                         * calc_debug
                                         * calc_debug:resource_debug
                                         * calc_debug:resource_debug:user_debug
                                         */
                                        if (nextcp(&cp, &index, argc, argv,
                                                   false)) {
                                            fprintf(stderr,
                                                    "-D expects argument\n");
                                            exit(5);
                                        }
                                        havearg = true;
                                        if (*cp != ':') {
                                                if (*cp < '0' || *cp > '9') {
                                                    fprintf(stderr,
                                                            "-D expects"
                                                            " integer\n");
                                                    exit(6);
                                                }
                                                calc_debug = cp;
                                                (void) strtol(cp, &endcp, 10);
                                                cp = endcp;
                                                if (*cp != '\0' &&
                                                    *cp != ' ' && *cp != ':') {
                                                    fprintf(stderr,
                                                            "Bad syntax im -D"
                                                            " arg\n");
                                                    exit(7);
                                                }
                                                if (*cp != ':') {
                                                    if (nextcp(&cp, &index,
                                                               argc, argv,
                                                               false)
                                                                || *cp != ':')
                                                        break;
                                                }
                                        }
                                        if (nextcp(&cp, &index, argc, argv,
                                                   false)) {
                                                fprintf(stderr,
                                                        "-D : expects"
                                                        " argument\n");
                                                exit(8);
                                        }
                                        if (*cp != ':') {
                                                if (*cp < '0' || *cp > '9') {
                                                    fprintf(stderr,
                                                            "-D : expects"
                                                            " integer\n");
                                                    exit(9);
                                                }
                                                resource_debug = cp;
                                                (void) strtol(cp, &endcp, 10);
                                                cp = endcp;
                                                if (*cp != '\0' &&
                                                    *cp != ' ' && *cp != ':') {
                                                    fprintf(stderr,
                                                            "Bad syntax im -D"
                                                            " : arg\n");
                                                    exit(10);
                                                }
                                                if (*cp != ':') {
                                                        if (nextcp(&cp, &index,
                                                                   argc, argv,
                                                                   false)
                                                            || *cp != ':') {
                                                                break;
                                                        }
                                                }
                                        }
                                        if (nextcp(&cp, &index, argc, argv,
                                                   false)) {
                                            fprintf(stderr, "-D : : expects"
                                                    " argument\n");
                                            exit(11);
                                        }
                                        if (*cp < '0' || *cp > '9') {
                                            fprintf(stderr, "-D :: expects"
                                                    " integer\n");
                                            exit(12);
                                        }
                                        user_debug = cp;
                                        (void) strtol(cp, &endcp, 10);
                                        cp = endcp;
                                        if (*cp != '\0' && *cp != ' ') {
                                                fprintf(stderr, "Bad syntax in"
                                                        " -D : : arg\n");
                                                exit(13);
                                        }
                                        break;
                                case 'f':
                                        haveendstr = (cp[1] == '\0');
                                        if (nextcp(&cp, &index, argc, argv,
                                                   haveendstr)) {
                                            fprintf(stderr, "-f expects"
                                                    " filename\n");
                                            exit(14);
                                        }
                                        if (*cp == ';') {
                                                fprintf(stderr,
                                                        "-f expects"
                                                        " filename\n");
                                                exit(15);
                                        }
                                        havearg = true;
                                        if (cmdlen > 0)
                                                cmdbuf[cmdlen++] = ' ';
                                        strlcpy(cmdbuf + cmdlen, "read ",
                                                sizeof("read "));
                                        cmdlen += sizeof("read ")-1;
                                        cmdbuf[cmdlen] = '\0';
                                        if (strncmp(cp, "-once",
                                                    sizeof("-once")) == 0 &&
                                            (cp[sizeof("-once")-1] == '\0' ||
                                             cp[sizeof("-once")-1] == ' ')) {
                                                cp += sizeof("-once")-1;
                                                haveendstr = (*cp == '\0');
                                                strlcpy(cmdbuf+cmdlen, "-once ",
                                                        sizeof("-once "));
                                                cmdlen += sizeof("-once ")-1;
                                                cmdbuf[cmdlen] = '\0';
                                                if (nextcp(&cp, &index, argc,
                                                           argv, haveendstr)) {
                                                    fprintf(stderr, "-f -once"
                                                            " expects"
                                                            " filename\n");
                                                    exit(16);
                                                }
                                        }
                                        bp = cmdbuf + cmdlen;
                                        /*
                                         * duplicate -f filename arg
                                         * as a new script_name value
                                         */
                                        if (script_name != NULL) {
                                                free(script_name);
                                        }
                                        script_name = NULL;
                                        script_name = strdup(cp);
                                        if (script_name == NULL) {
                                                fprintf(stderr,
                                                        "strdup(-f argument)"
                                                        "failed\n");
                                                exit(17);
                                        }
                                        /* process -f filename arg */
                                        if (haveendstr) {
                                                len = strlen(cp);
                                                if (len == 0) {
                                                        fprintf(stderr,
                                                                "Null"
                                                                " filename!\n");
                                                        exit(18);
                                                }
                                                if (cmdlen + len + 2 > MAXCMD) {
                                                        fprintf(stderr,
                                                                "Commands too"
                                                                " long\n");
                                                        exit(19);
                                                }
                                                /* XXX - what if *cp = '\''? */
                                                *bp++ = '\'';
                                                strlcpy(bp, cp, len+1);
                                                bp += len;
                                                *bp++ = '\'';
                                                cp += len;
                                                cmdlen += len + 2;
                                        } else {
                                                do {
                                                        if (cmdlen > MAXCMD) {
                                                            fprintf(stderr,
                                                               "Commands"
                                                               " too long\n");
                                                            exit(20);
                                                        }
                                                        *bp++ =  *cp++;
                                                        cmdlen++;
                                                } while (*cp != '\0' &&
                                                         *cp != ';' &&
                                                         *cp != ' ');
                                        }
                                        if (*cp == ';')
                                                cp++;
                                        *bp++ = ';';
                                        *bp = '\0';
                                        cmdlen++;

                                        /* -f implies -s */
                                        s_flag = true;
                                        maxindex = index + 1;
                                        break;

                                case 's':
                                        s_flag = true;
                                        maxindex = index + 1;
                                        break;
                                default:
                                        /*
                                         * we are too early in processing to
                                         * call libcalc_call_me_last() -
                                         * nothing to cleanup
                                         */
                                        fprintf(stderr, "Illegal option -%c\n",
                                                        c);
                                        fprintf(stderr,
                "usage: %s [-c] [-C] [-d] [-e] [-h] [-i] [-m mode]\n"
                "\t[-D calc_debug[:resource_debug[:user_debug]]]\n"
                "\t[-O] [-p] [-q] [-s] [-u] [-v] "
                "[--] [calc_cmd ...]\n"
                "usage: %s ... -f filename\n"
                "1st cscript line: #/path/to/calc ... -s -f\n",
                program, program);
                                        exit(21);
                        }
                        if (havearg)
                                break;
                        cp++;
                        }
                        while (*cp == ' ')
                                cp++;
                        if (*cp == '\0') {
                                index++;
                                break;
                        }
                }
        }

        while (index < maxindex) {
                size_t cplen;

                if (cmdlen > 0)
                        cmdbuf[cmdlen++] = ' ';
                cplen = strlen(cp);
                newcmdlen = cmdlen + cplen;
                if (newcmdlen > MAXCMD) {
                        fprintf(stderr,
                                "%s: commands too long\n",
                                program);
                        exit(22);
                }
                strlcpy(cmdbuf + cmdlen, cp, cplen+1);
                cmdbuf[newcmdlen] = '\0';
                cmdlen = newcmdlen;
                index++;
                if (index < maxindex)
                        cp = argv[index];
        }

        havecommands = (cmdlen > 0);

        if (havecommands) {
                cmdbuf[cmdlen++] = '\n';
                cmdbuf[cmdlen] = '\0';
                if (p_flag != true) {
                        if (freopen("/dev/null", "r", stdin) == NULL) {
                                perror("in main: freopen(\"/dev/null\", \"r\", stdin) failed:");
                        }
                        stdin_closed = true;
                }
        }

        argc_value = argc - maxindex + 1;
        argv_value = argv + maxindex;

        /*
         * unbuffered mode
         */
        if (u_flag) {
                if (stdin_closed == false) {
                        setbuf(stdin, NULL);
                }
                setbuf(stdout, NULL);
        }

        /*
         * initialize
         */
        libcalc_call_me_first();
        if (u_flag) {
                if (conf->calc_debug & CALCDBG_TTY) {
                        if (stdin_closed == false) {
                                printf("main: stdin set to unbuffered before "
                                       "calling libcalc_call_me_first()\n");
                        } else {
                                printf("main: stdin closed before "
                                       "calling libcalc_call_me_first()\n");
                        }
                }
        }
        stdin_tty = isatty(0);          /* assume stdin is on fd 0 */
        if (conf->calc_debug & CALCDBG_TTY)
                printf("main: stdin_tty is %d\n", stdin_tty);
        if (want_defhelp) {
                givehelp(DEFAULTCALCHELP);
                libcalc_call_me_last();
                exit(0);
        }

        /*
         * if allowed or needed, print version and setup bindings
         */
        if (!havecommands && stdin_tty) {
                if (!d_flag) {
                        printf("%s (version %s)\n", CALC_TITLE, version());
                        printf("Calc is open software. For license details "
                               "type:  help copyright\n");
                        printf("[%s]\n\n",
                            "Type \"exit\" to exit, or \"help\" for help.");
                }
                switch (hist_init(calcbindings)) {
                case HIST_NOFILE:
                        fprintf(stderr,
                            "%s: Cannot open bindings file \"%s\", "
                            "fancy editing disabled.\n",
                             program, calcbindings);
                        break;

                case HIST_NOTTY:
                        fprintf(stderr,
                                "%s: Cannot set terminal modes, "
                                "fancy editing disabled\n", program);
                        break;
                }
        }

        /*
         * establish error longjump point with initial conditions
         */
        if (setjmp(calc_scanerr_jmpbuf) == 0) {

                /*
                 * reset/initialize the computing environment
                 */
                initialize();
                calc_use_scanerr_jmpbuf = 1;
        }

        /*
         * (re)establish the interrupt handler
         */
        (void) signal(SIGINT, intint);

        /*
         * execute calc code based on the run state
         */
        if (run_state == RUN_BEGIN) {
                if (!q_flag && allow_read) {
                        set_run_state(RUN_RCFILES);
                        runrcfiles();
                }
                set_run_state(RUN_PRE_CMD_ARGS);
        }

        while (run_state == RUN_RCFILES) {
                fprintf(stderr, "Error in rcfiles\n");
                if ((c_flag && !stoponerror) || stoponerror < 0) {
                        getcommands(false);
                        if (inputlevel() == 0) {
                                closeinput();
                                runrcfiles();
                                set_run_state(RUN_PRE_CMD_ARGS);
                        } else {
                                closeinput();
                        }
                } else {
                        if ((havecommands && !i_flag) || !stdin_tty) {
                                set_run_state(RUN_EXIT_WITH_ERROR);
                        } else {
                                set_run_state(RUN_PRE_CMD_ARGS);
                        }
                }
        }

        if (run_state == RUN_PRE_CMD_ARGS) {
                if (havecommands) {
                        set_run_state(RUN_CMD_ARGS);
                        (void) openstring(cmdbuf, strlen(cmdbuf));
                        getcommands(false);
                        closeinput();
                }
                set_run_state(RUN_PRE_TOP_LEVEL);
        }

        while (run_state == RUN_CMD_ARGS) {
                fprintf(stderr, "Error in commands\n");
                if ((c_flag && !stoponerror) || stoponerror < 0) {
                        getcommands(false);
                        if (inputlevel() == 0)
                                set_run_state(RUN_PRE_TOP_LEVEL);
                        closeinput();
                } else {
                        closeinput();
                        if (!stdin_tty || !i_flag || p_flag) {
                                set_run_state(RUN_EXIT_WITH_ERROR);
                        } else {
                                set_run_state(RUN_PRE_TOP_LEVEL);
                        }
                }
        }

        if (run_state == RUN_PRE_TOP_LEVEL) {
                if (stdin_tty &&
                    (((havecommands) && !i_flag) || p_flag)) {
                        set_run_state(RUN_EXIT);
                } else {
                        if (stdin_tty) {
                                reinitialize();
                        } else {
                                resetinput();
                                openterminal();
                        }
                        set_run_state(RUN_TOP_LEVEL);
                        getcommands(true);
                }
                if (p_flag || (!i_flag && havecommands))
                        set_run_state(RUN_EXIT);
        }

        while (run_state == RUN_TOP_LEVEL) {
                if (conf->calc_debug & CALCDBG_RUNSTATE)
                        printf("main: run_state = TOP_LEVEL\n");
                if ((c_flag && !stoponerror) || stoponerror < 0) {
                        getcommands(true);
                        if (!inputisterminal()) {
                                closeinput();
                                continue;
                        }
                        if (!p_flag && i_flag && !stdin_tty) {
                                closeinput();
                                if(!freopen("/dev/tty", "r", stdin)) {
#if defined(_WIN32) || defined(_WIN64)
                                        fprintf(stderr,
                                                "/dev/tty does not exist on "
                                                "this operating system.  "
                                                "Change operating systems\n"
                                                "or don't use this calc mode "
                                                "in the future, sorry!\n");
#else /* Windows free systems */
                                        fprintf(stderr,
                                                "Unable to associate stdin"
                                                " with /dev/tty");
#endif /* Windows free systems */
                                        set_run_state(RUN_EXIT_WITH_ERROR);
                                        break;
                                }

                                stdin_tty = true;
                                if (conf->calc_debug & CALCDBG_TTY)
                                        printf("main: stdin_tty is %d\n",
                                               stdin_tty);
                                reinitialize();
                        }
                } else {
                        if (stdin_tty) {
                                reinitialize();
                                getcommands(true);
                        } else if (inputisterminal() &&
                                        !p_flag && (!havecommands||i_flag)) {
                                closeinput();
                                if(!freopen("/dev/tty", "r", stdin)) {
#if defined(_WIN32) || defined(_WIN64)
                                        fprintf(stderr,
                                                "/dev/tty does not exist on "
                                                "this operating system.  "
                                                "Change operating systems\n"
                                                "or don't use this calc mode "
                                                "in the future, sorry!\n");
#else /* Windows free systems */
                                        fprintf(stderr,
                                                "Unable to associate stdin"
                                                " with /dev/tty");
#endif /* Windows free systems */
                                        set_run_state(RUN_EXIT_WITH_ERROR);
                                        break;
                                }
                                stdin_tty = true;
                                if (conf->calc_debug & CALCDBG_TTY)
                                        printf("main: stdin_tty is %d\n",
                                               stdin_tty);
                                reinitialize();
                        } else {
                                set_run_state(RUN_EXIT_WITH_ERROR);
                        }
                }
        }
        if (conf->calc_debug & CALCDBG_RUNSTATE)
                printf("main: run_state = %s\n", run_state_name(run_state));

        /*
         * All done! - Jessica Noll, Age 2
         */
        libcalc_call_me_last();
        return (run_state == RUN_EXIT_WITH_ERROR ||
                run_state == RUN_ZERO) ? 1 : 0;
}


/*
 * Interrupt routine.
 *
 * given:
 *      arg             to keep ANSI C happy
 */
/*ARGSUSED*/
S_FUNC void
intint(int UNUSED(arg))
{
        (void) signal(SIGINT, intint);
        if (inputwait || (++abortlevel >= ABORT_NOW)) {
                calc_interrupt("\nABORT");
                not_reached();
        }
        if (abortlevel >= ABORT_MATH)
                _math_abort_ = true;
        printf("\n[Abort level %d]\n", abortlevel);
}


/*
 * report an interrupt
 */
static void
calc_interrupt(char *fmt, ...)
{
        va_list ap;

        if (funcname && (*funcname != '*'))
                fprintf(stderr, "\"%s\": ", funcname);
        if (funcline && ((funcname && (*funcname != '*')) ||
            !inputisterminal()))
                fprintf(stderr, "line %ld: ", funcline);
        va_start(ap, fmt);
        vsnprintf(calc_err_msg, MAXERROR, fmt, ap);
        va_end(ap);
        calc_err_msg[MAXERROR] = '\0';  /* paranoia */
        fprintf(stderr, "%s\n\n", calc_err_msg);
        funcname = NULL;
        if (calc_use_scanerr_jmpbuf != 0) {
                longjmp(calc_scanerr_jmpbuf, 22);
        } else {
                fprintf(stderr, "It is too early provide a command line prompt "
                                "so we must simply exit.  Sorry!\n");
                /*
                 * don't call libcalc_call_me_last() -- we might loop
                 * and besides ... this is an unusual internal error case
                 */
                exit(24);
        }
}

S_FUNC int
nextcp(char **cpp, int *ip, int argc, char **argv, bool haveendstr)
{
        char *cp;
        int index;

        cp = *cpp;
        index = *ip;


        if (haveendstr) {
                index++;
                *ip = index;
                if (index >= argc)
                        return 1;
                *cpp = argv[index];
                return 0;
        }

        if (*cp != '\0')
                cp++;
        for (;;) {
                if (*cp == '\0') {
                        index++;
                        *ip = index;
                        if (index >= argc)
                                return 1;
                        cp = argv[index];
                }
                while (*cp == ' ')
                        cp++;
                if (*cp != '\0')
                        break;
        }
        *cpp = cp;
        return 0;
}


S_FUNC void
set_run_state(run state)
{
        if (conf->calc_debug & CALCDBG_RUNSTATE)
                printf("main: run_state from %s to %s\n",
                            run_state_name(run_state),
                            run_state_name(state));
        run_state = state;
}

