mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Release calc version 2.11.0t10.5.1
This commit is contained in:
421
lib_calc.c
421
lib_calc.c
@@ -1,37 +1,29 @@
|
||||
/*
|
||||
* lib_calc - calc link library initialization and shutdown routines
|
||||
* Copyright (c) 1997 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Copyright (C) 1999 Landon Curt Noll
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* 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.
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* 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.
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* 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.
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* @(#) $Revision: 29.2 $
|
||||
* @(#) $Id: lib_calc.c,v 29.2 1999/12/14 19:37:46 chongo Exp $
|
||||
* @(#) $Source: /usr/local/src/cmd/calc/RCS/lib_calc.c,v $
|
||||
*
|
||||
* Under source code control: 1996/06/17 18:06:19
|
||||
* File existed as early as: 1996
|
||||
*
|
||||
* chongo <was here> /\oo/\ http://reality.sgi.com/chongo/
|
||||
* Share and enjoy! :-) http://reality.sgi.com/chongo/tech/comp/calc/
|
||||
* chongo was here /\../\
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "calc.h"
|
||||
@@ -57,24 +49,6 @@
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "terminal.h"
|
||||
#if defined(USE_TERMIOS)
|
||||
|
||||
# include <termios.h>
|
||||
typedef struct termios ttystruct;
|
||||
|
||||
#elif defined(USE_TERMIOS)
|
||||
|
||||
# include <termio.h>
|
||||
typedef struct termio ttystruct;
|
||||
|
||||
#else /* assume USE_SGTTY */
|
||||
|
||||
# include <sys/ioctl.h>
|
||||
typedef struct sgttyb ttystruct;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* in case we do not have certain .h files
|
||||
*/
|
||||
@@ -95,7 +69,6 @@ int abortlevel; /* current level of aborts */
|
||||
BOOL inputwait; /* TRUE if in a terminal input wait */
|
||||
jmp_buf jmpbuf; /* for errors */
|
||||
char *program = "calc"; /* our name */
|
||||
char *base_name = "calc"; /* basename of our name */
|
||||
char cmdbuf[MAXCMD+1+1+1]; /* command line expression + "\n\0" + guard */
|
||||
run run_state = RUN_UNKNOWN; /* calc startup and run state */
|
||||
|
||||
@@ -114,10 +87,9 @@ int allow_exec = TRUE; /* FALSE => may not execute any commands */
|
||||
int p_flag = FALSE; /* TRUE => pipe mode */
|
||||
int q_flag = FALSE; /* TRUE => don't execute rc files */
|
||||
int u_flag = FALSE; /* TRUE => unbuffer stdin and stdout */
|
||||
int d_flag = FALSE; /* TRUE => disable heading, resource_debug == 0 */
|
||||
int d_flag = FALSE; /* TRUE => disable heading, lib_debug == 0 */
|
||||
int c_flag = FALSE; /* TRUE => continue on error if permitted */
|
||||
int i_flag = FALSE; /* TRUE => go interactive if permitted */
|
||||
int s_flag = FALSE; /* TRUE => keep args as strings for argv() */
|
||||
|
||||
|
||||
/*
|
||||
@@ -135,16 +107,13 @@ int stoponerror = FALSE; /* >0 => stop, <0 => continue on error */
|
||||
int post_init = FALSE; /* TRUE setjmp for math_error is ready */
|
||||
BOOL abort_now = FALSE; /* TRUE => go interactive now, if permitted */
|
||||
|
||||
int argc_value = 0; /* count of argv[] strings for argv() builtin */
|
||||
char **argv_value = NULL; /* argv[] strings for argv() builtin */
|
||||
|
||||
int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */
|
||||
int errmax = ERRMAX; /* if >= 0, maximum value for errcount */
|
||||
|
||||
NUMBER *epsilon_default; /* default allowed error for float calcs */
|
||||
|
||||
char *calc_debug = NULL; /* !=NULL => value of config("calc_debug") */
|
||||
char *resource_debug = NULL; /* !=NULL => config("resource_debug") value */
|
||||
char *lib_debug = NULL; /* !=NULL => value of config("lib_debug") */
|
||||
char *user_debug = NULL; /* !=NULL => value of config("user_debug") */
|
||||
|
||||
|
||||
@@ -162,12 +131,7 @@ extern void reinitialize(void);
|
||||
* static declarations
|
||||
*/
|
||||
static int init_done = 0; /* 1 => we already initialized */
|
||||
static int *fd_setup = NULL; /* fd's setup for interaction or -1 */
|
||||
static int fd_setup_len = 0; /* number of fd's in fd_setup */
|
||||
static ttystruct *fd_orig = NULL; /* fd original state */
|
||||
static ttystruct *fd_cur = NULL; /* fd current atate */
|
||||
static void initenv(void); /* setup calc environment */
|
||||
static int find_tty_state(int fd); /* find slot for saved tty state */
|
||||
static void initenv(void);
|
||||
|
||||
|
||||
/*
|
||||
@@ -179,8 +143,6 @@ static int find_tty_state(int fd); /* find slot for saved tty state */
|
||||
void
|
||||
libcalc_call_me_first(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* do nothing if we are initialized already
|
||||
*/
|
||||
@@ -189,30 +151,9 @@ libcalc_call_me_first(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable SIGPIPE so that the pipe to the help file pager will
|
||||
* not stop calc.
|
||||
*/
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/*
|
||||
* determine the basename
|
||||
*/
|
||||
if (program != NULL) {
|
||||
p = strrchr(program, '/');
|
||||
if (p == NULL) {
|
||||
base_name = program;
|
||||
} else {
|
||||
base_name = p+1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize old and new configuration values
|
||||
* setup configuration values
|
||||
*/
|
||||
oldstd.epsilon = &_qonesqbase_; /* magic to fake early str2q() */
|
||||
oldstd.program = strdup(program);
|
||||
oldstd.base_name = strdup(base_name);
|
||||
oldstd.version = strdup(version());
|
||||
conf = config_copy(&oldstd); /* more magic to fake early str2q() */
|
||||
conf->tab_ok = FALSE;
|
||||
oldstd.epsilon = str2q(EPSILON_DEFAULT);
|
||||
@@ -229,10 +170,10 @@ libcalc_call_me_first(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* -d turns off resource_debug
|
||||
* -d turns off lib_debug
|
||||
*/
|
||||
if (d_flag) {
|
||||
conf->resource_debug = 0;
|
||||
conf->lib_debug = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -243,13 +184,13 @@ libcalc_call_me_first(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* -D flags can change calc_debug, resource_debug of user_debug
|
||||
* -D flags can change calc_debug, lib_debug of user_debug
|
||||
*/
|
||||
if (calc_debug) {
|
||||
conf->calc_debug = strtol(calc_debug, NULL, 0);
|
||||
}
|
||||
if (resource_debug) {
|
||||
conf->resource_debug = strtol(resource_debug, NULL, 0);
|
||||
if (lib_debug) {
|
||||
conf->lib_debug = strtol(lib_debug, NULL, 0);
|
||||
}
|
||||
if (user_debug) {
|
||||
conf->user_debug = strtol(user_debug, NULL, 0);
|
||||
@@ -264,7 +205,7 @@ libcalc_call_me_first(void)
|
||||
* ready to rock & roll ..
|
||||
*/
|
||||
if (conf->calc_debug & CALCDBG_RUNSTATE) {
|
||||
printf("libcalc_call_me_first: run_state from %s to %s\n",
|
||||
printf("DEBUG: run_state from %s to %s\n",
|
||||
run_state_name(run_state),
|
||||
run_state_name(RUN_BEGIN));
|
||||
}
|
||||
@@ -439,8 +380,6 @@ initenv(void)
|
||||
void
|
||||
libcalc_call_me_last(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
@@ -458,21 +397,6 @@ libcalc_call_me_last(void)
|
||||
*/
|
||||
random_libcalc_cleanup();
|
||||
|
||||
/*
|
||||
* restore all changed descriptor states
|
||||
*/
|
||||
if (fd_setup_len > 0) {
|
||||
for (i=0; i < fd_setup_len; ++i) {
|
||||
if (fd_setup[i] >= 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("libcalc_call_me_last: fd %d "
|
||||
"not in original state, "
|
||||
"restoring it", fd_setup[i]);
|
||||
orig_tty(fd_setup[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* all done
|
||||
*/
|
||||
@@ -551,294 +475,3 @@ calc_strdup(CONST char *s1)
|
||||
|
||||
#endif /* HAVE_STRDUP */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* find_tty_state - establish a new tty state
|
||||
*
|
||||
* Given:
|
||||
* fd file descriptor to establish a new tty state for
|
||||
*
|
||||
* Returns:
|
||||
* indx The index into fd_setup[], fd_orig[] and fd_cur[] to use or -1
|
||||
*/
|
||||
static int
|
||||
find_tty_state(int fd)
|
||||
{
|
||||
int *new_fd_setup; /* new fd_setup array */
|
||||
ttystruct *new_fd_orig; /* new fd_orig array */
|
||||
ttystruct *new_fd_cur; /* new fd_cur array */
|
||||
int i;
|
||||
|
||||
/*
|
||||
* firewall: must be > 0
|
||||
*/
|
||||
if (fd < 0) {
|
||||
/* bad descriptor */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* case: need to initlally malloc some state
|
||||
*/
|
||||
if (fd_setup_len <= 0 || fd_setup == NULL || fd_orig == NULL) {
|
||||
|
||||
/* setup for a single descriptor */
|
||||
fd_setup = (int *)malloc(sizeof(fd_setup[0]));
|
||||
if (fd_setup == NULL) {
|
||||
return -1;
|
||||
}
|
||||
fd_setup[0] = -1;
|
||||
fd_orig = (ttystruct *)malloc(sizeof(fd_orig[0]));
|
||||
if (fd_orig == NULL) {
|
||||
return -1;
|
||||
}
|
||||
fd_cur = (ttystruct *)malloc(sizeof(fd_orig[0]));
|
||||
if (fd_cur == NULL) {
|
||||
return -1;
|
||||
}
|
||||
fd_setup_len = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for an existing tty state for the descriptor
|
||||
*/
|
||||
for (i=0; i < fd_setup_len; ++i) {
|
||||
|
||||
/* case: found existing tty state, return index */
|
||||
if (fd_setup[i] == fd) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* no tty state exists for the descriptor, look for empty slot
|
||||
*/
|
||||
for (i=0; i < fd_setup_len; ++i) {
|
||||
|
||||
/* case: found an empty slot, so return it */
|
||||
if (fd_setup[i] < 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* no empty slots exist, realloc another slot
|
||||
*/
|
||||
new_fd_setup = (int *)realloc(fd_setup, sizeof(fd_setup[0]) *
|
||||
(fd_setup_len+1));
|
||||
if (new_fd_setup == NULL) {
|
||||
return -1;
|
||||
}
|
||||
new_fd_setup[fd_setup_len] = -1;
|
||||
new_fd_orig = (ttystruct *)realloc(fd_setup, sizeof(fd_orig[0]) *
|
||||
(fd_setup_len+1));
|
||||
if (new_fd_orig == NULL) {
|
||||
return -1;
|
||||
}
|
||||
new_fd_cur = (ttystruct *)realloc(fd_cur, sizeof(fd_cur[0]) *
|
||||
(fd_setup_len+1));
|
||||
if (new_fd_cur == NULL) {
|
||||
return -1;
|
||||
}
|
||||
fd_setup = new_fd_setup;
|
||||
fd_orig = new_fd_orig;
|
||||
fd_cur = new_fd_cur;
|
||||
++fd_setup_len;
|
||||
/* return the new slot */
|
||||
return fd_setup_len-1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* calc_tty - setup a file descriptor for calc's interactive use
|
||||
*
|
||||
* Calc wants, in effect, cbreak on and echo off.
|
||||
*
|
||||
* Given:
|
||||
* fd the descriptor for calc's interactive use
|
||||
*
|
||||
* Returns:
|
||||
* TRUE state change was successful
|
||||
* FALSE unable to change state of descriptor for interactive use
|
||||
*/
|
||||
BOOL
|
||||
calc_tty(int fd)
|
||||
{
|
||||
int slot; /* the saved descriptor slot or -1 */
|
||||
|
||||
/*
|
||||
* grab the saved slot for this descriptor
|
||||
*/
|
||||
slot = find_tty_state(fd);
|
||||
if (slot < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot get saved descriptor slot\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if defined(USE_SGTTY)
|
||||
|
||||
/*
|
||||
* USE_SGTTY tty state method
|
||||
*/
|
||||
/* save original state if needed */
|
||||
if (fd_setup[slot] < 0 && ioctl(fd, TIOCGETP, fd_orig+slot) < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot TIOCGETP fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
/* setup for new state */
|
||||
fd_cur[slot] = fd_orig[slot];
|
||||
fd_cur[slot].sg_flags &= ~ECHO;
|
||||
fd_cur[slot].sg_flags |= CBREAK;
|
||||
/* enable new state */
|
||||
if (ioctl(fd, TIOCSETP, fd_cur+slot) < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot TIOCSETP fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: stty -ECHO +CBREAK: fd %d\n", fd);
|
||||
|
||||
#elif defined(USE_TERMIO)
|
||||
|
||||
/*
|
||||
* USE_TERMIO tty state method
|
||||
*/
|
||||
if (fd_setup[slot] < 0 && ioctl(fd, TCGETA, fd_orig+slot) < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot TCGETA fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
/* setup for new state */
|
||||
fd_cur[slot] = fd_orig[slot];
|
||||
fd_cur[slot].c_lflag &= ~(ECHO | ECHOE | ECHOK);
|
||||
fd_cur[slot].c_iflag |= ISTRIP;
|
||||
fd_cur[slot].c_lflag &= ~ICANON;
|
||||
fd_cur[slot].c_cc[VMIN] = 1;
|
||||
fd_cur[slot].c_cc[VTIME] = 0;
|
||||
/* enable new state */
|
||||
if (ioctl(fd, TCSETAW, fd_cur+slot) < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot TCSETAW fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: stty -ECHO -ECHOE -ECHOK -ICANON +ISTRIP "
|
||||
"VMIN=1 VTIME=0: fd %d\n", fd);
|
||||
|
||||
#else /* assume USE_SGTTY */
|
||||
|
||||
/*
|
||||
* assume USE_SGTTY tty state method
|
||||
*/
|
||||
if (fd_setup[slot] < 0 && tcgetattr(fd, fd_orig+slot) < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot tcgetattr fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
/* setup for new state */
|
||||
fd_cur[slot] = fd_orig[slot];
|
||||
fd_cur[slot].c_lflag &= ~(ECHO | ECHOE | ECHOK);
|
||||
fd_cur[slot].c_iflag |= ISTRIP;
|
||||
fd_cur[slot].c_lflag &= ~ICANON;
|
||||
fd_cur[slot].c_cc[VMIN] = 1;
|
||||
fd_cur[slot].c_cc[VTIME] = 0;
|
||||
/* enable new state */
|
||||
if (tcsetattr(fd, TCSANOW, fd_cur+slot) < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: Cannot tcsetattr fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("calc_tty: stty -ECHO -ECHOE -ECHOK -ICANON +ISTRIP "
|
||||
"VMIN=1 VTIME=0: fd %d\n", fd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* note that the tty slot is on use
|
||||
*/
|
||||
fd_setup[slot] = fd;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* orig_tty - restore the original state of a file descriptor
|
||||
*
|
||||
* This routine will restore the state of a descriptor to its calc
|
||||
* startup value if it was set for interactive use by calc_tty().
|
||||
*
|
||||
* Given:
|
||||
* fd the descriptor to restore
|
||||
*
|
||||
* Returns:
|
||||
* TRUE restore was successful
|
||||
* FALSE unable to restore descriptor to original state
|
||||
*/
|
||||
BOOL
|
||||
orig_tty(int fd)
|
||||
{
|
||||
int slot; /* the saved descriptor slot or -1 */
|
||||
|
||||
/*
|
||||
* find the saved slot for this descriptor
|
||||
*/
|
||||
slot = find_tty_state(fd);
|
||||
if (slot < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("orig_tty: Cannot get saved descriptor slot\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* do nothing if no state was saved for this descriptor
|
||||
*/
|
||||
if (fd_setup[slot] < 0) {
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("orig_tty: no state saved for fd %d\n", fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if defined(USE_SGTTY)
|
||||
|
||||
/*
|
||||
* USE_SGTTY tty state method
|
||||
*/
|
||||
(void) ioctl(fd, TIOCSETP, fd_orig+slot);
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("orig_tty: TIOCSETP restored fd %d\n", fd);
|
||||
|
||||
#elif defined(USE_TERMIO)
|
||||
|
||||
/*
|
||||
* USE_TERMIO tty state method
|
||||
*/
|
||||
(void) ioctl(fd, TCSETAW, fd_orig+slot);
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("orig_tty: TCSETAW restored fd %d\n", fd);
|
||||
|
||||
#else /* assume USE_SGTTY */
|
||||
|
||||
/*
|
||||
* assume USE_SGTTY tty state method
|
||||
*/
|
||||
(void) tcsetattr(fd, TCSANOW, fd_orig+slot);
|
||||
if (conf->calc_debug & CALCDBG_TTY)
|
||||
printf("orig_tty: TCSANOW restored fd %d\n", fd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* note new current state
|
||||
*/
|
||||
fd_cur[slot] = fd_orig[slot];
|
||||
|
||||
/*
|
||||
* Since current state is the orignal state, we can free up
|
||||
* this slot. This also prevents functins such as the
|
||||
* libcalc_call_me_last() function from re-restoring it.
|
||||
*/
|
||||
fd_setup[slot] = -1;
|
||||
return TRUE;
|
||||
}
|
||||
|
Reference in New Issue
Block a user