Compare commits

...

2 Commits

Author SHA1 Message Date
Landon Curt Noll
35982c7cc8 Release calc version 2.11.0t7.1 2017-05-21 15:38:28 -07:00
Landon Curt Noll
4c0f2691e9 Release calc version 2.11.0t7 2017-05-21 15:38:28 -07:00
17 changed files with 424 additions and 133 deletions

108
CHANGES
View File

@@ -1,4 +1,110 @@
Following is the change from calc version 2.11.0t1 to date: Following is the change from calc version 2.11.0t7 to date:
Calc has some new command line flags / command line meaning:
(Thanks goes to Ernest Bowen <ernie@turing.une.edu.au>)
-i Go into interactive mode if possible.
-c Continue reading command lines even after an execution
error has caused the abandonment of a line
To understand the -i and -c effects, consider the following
file (call it myfile.cal) which has deliberate errors in it:
print 1;
mat A[1] = {2,3};
print 2;
epsilon(-1);
print 3;
calc read myfile
Reports an error on the 2nd line and exits; prints 1 only.
calc -c read myfile
Report errors on the 2nd and 4th lines and exits; prints 1,2 and 3.
calc -i read myfile
Report errors on the 2nd and gives you a prompt; prints 1 only.
calc -i -c read myfile
Report errors on the 2nd and 4th and gives you a prompt;
prints 1, 2 and 3.
cat myfile | calc
Reports an error on the 2nd line and exits; prints 1 only.
cat myfile | calc -c
Report errors on the 2nd and 4th lines and exits; prints 1,2 and 3.
Note that continuation refers to command lines, not to statements. So:
calc -c 'print "start"; mat A[1] = {2,3}; print "end";'
since it contains no newline, the whole string is compiled,
but execution is abandoned when the error is encountered and
the string ``end'' is not printed.
You can use your shell to supply newlines in your command line
arguments. For example in sh, ksh, bash:
calc -c 'print "start";
mat A[1] = {2,3};
print "end";'
will print both ``start'' and ``end''. C-shell users can do:
calc -c 'print "start"; \
mat A[1] = {2,3}; \
print "end";'
however sh, ksh, bash will not see ``end'' printed because their
shell will remove the internal newlines.
Added display(n) builtin which does almost the same as config("display",n)
except that rather than causing an execution with an out-of-range or
bad-type argument type, it simply writes a message to stderr. This
also now happens to the errmax() builtin.
Added qtime.cal to the standard calc library.
Added another command line flag to calc:
-d Disable display of the opening title and config("lib_debug",0)
The command:
calc 'read qtime; qtime(2)'
will output something like:
qtime(utc_hr_offset) defined
It's nearly ten past six.
whereas:
calc -d 'read qtime; qtime(2)'
will just say:
It's nearly ten past six.
A call of errmax(-1) will prevent errcount from aborting calc.
Add the function stoponerror(n) which, as the name implies, controls
if calc stop on an error based on the value of n:
n > 0 stop on error even if -c was given on the command line
n == 0 if -c, continue, without -c, stop
n < 0 continue on error, even if -c was given on the command line
Following is the change from calc version 2.11.0t1 to 2.11.0t6.3:
Removed the makefile symbol MAIN. Now forcing all functions to correctly Removed the makefile symbol MAIN. Now forcing all functions to correctly
be declared main. To satisfy some old broken compilers, a return 0; be declared main. To satisfy some old broken compilers, a return 0;

View File

@@ -2259,11 +2259,11 @@ bsdilist: ${DISTLIST} ${BUILD_H_SRC} calc.1
## ##
check: all ./lib/regress.cal ${REGRESS_CAL} check: all ./lib/regress.cal ${REGRESS_CAL}
${CALC_ENV} ./calc -i -q read regress ${CALC_ENV} ./calc -d -q read regress
chk: ./lib/regress.cal ${REGRESS_CAL} chk: ./lib/regress.cal ${REGRESS_CAL}
${V} echo '=-=-=-=-= start of $@ rule =-=-=-=-=' ${V} echo '=-=-=-=-= start of $@ rule =-=-=-=-='
${CALC_ENV} ./calc -i -q read regress 2>&1 | ${AWK} -f check.awk ${CALC_ENV} ./calc -d -q read regress 2>&1 | ${AWK} -f check.awk
${V} echo '=-=-=-=-= end of $@ rule =-=-=-=-=' ${V} echo '=-=-=-=-= end of $@ rule =-=-=-=-='
## ##

View File

@@ -449,6 +449,11 @@ addop(long op)
case OP_GLOBALADDR: case OP_GLOBALADDR:
diff = 1 + PTR_SIZE; diff = 1 + PTR_SIZE;
break; break;
case OP_UNDEF:
fp->f_opcodecount -= 1;
oldop = OP_NOP;
oldoldop = OP_NOP;
return;
default: default:
cut = FALSE; cut = FALSE;
} }

134
calc.c
View File

@@ -49,6 +49,8 @@ extern int isatty(int tty); /* TRUE if fd is a tty */
extern int p_flag; /* TRUE => pipe mode */ extern int p_flag; /* TRUE => pipe mode */
extern int q_flag; /* TRUE => don't execute rc files */ extern int q_flag; /* TRUE => don't execute rc files */
extern int u_flag; /* TRUE => unbuffer stdin and stdout */ extern int u_flag; /* TRUE => unbuffer stdin and stdout */
extern int d_flag; /* TRUE => disable heading, lib_debug == 0 */
extern int stoponerror; /* >0 => stop, <0 => continue, ==0 => use -c */
extern char *pager; /* $PAGER or default */ extern char *pager; /* $PAGER or default */
extern int stdin_tty; /* TRUE if stdin is a tty */ extern int stdin_tty; /* TRUE if stdin is a tty */
@@ -63,9 +65,12 @@ extern char *version(void); /* return version string */
* static definitions and functions * static definitions and functions
*/ */
static char *usage = "usage: %s [-C] [-e] [-h] [-i] [-m mode] [-n] [-p]\n" static char *usage = "usage: %s [-C] [-e] [-h] [-i] [-m mode] [-n] [-p]\n"
"\t[-q] [-u] [[--] calc_cmd ...]\n"; "\t[-q] [-u] [-c] [-d] [[--] calc_cmd ...]\n";
static void intint(int arg); /* interrupt routine */ static void intint(int arg); /* interrupt routine */
static int havecommands;
static int c_flag; /* To permit continuation after error */
static int i_flag; /* To go interactive if permitted */
/* /*
* Top level calculator routine. * Top level calculator routine.
@@ -84,7 +89,7 @@ main(int argc, char **argv)
* parse args * parse args
*/ */
program = argv[0]; program = argv[0];
while ((c = getopt(argc, argv, "Cehim:npquv")) != -1) { while ((c = getopt(argc, argv, "Cehim:npquvcd")) != -1) {
switch (c) { switch (c) {
case 'C': case 'C':
#if defined(CUSTOM) #if defined(CUSTOM)
@@ -107,7 +112,7 @@ main(int argc, char **argv)
want_defhelp = 1; want_defhelp = 1;
break; break;
case 'i': case 'i':
ign_errmax = TRUE; i_flag = TRUE;
break; break;
case 'm': case 'm':
if (optarg[1] == '\0' || *optarg<'0' || *optarg>'7') { if (optarg[1] == '\0' || *optarg<'0' || *optarg>'7') {
@@ -136,6 +141,12 @@ main(int argc, char **argv)
case 'u': case 'u':
u_flag = TRUE; u_flag = TRUE;
break; break;
case 'c':
c_flag = TRUE;
break;
case 'd':
d_flag = TRUE;
break;
case 'v': case 'v':
/* /*
* we are too early in processing to call * we are too early in processing to call
@@ -153,6 +164,7 @@ main(int argc, char **argv)
} }
} }
interactive = (optind >= argc); interactive = (optind >= argc);
havecommands = !interactive;
/* /*
* look at the length of any trailing command args * look at the length of any trailing command args
@@ -201,8 +213,7 @@ main(int argc, char **argv)
* initialize * initialize
*/ */
libcalc_call_me_first(); libcalc_call_me_first();
stdin_tty = TRUE; /* assume internactive default */ stdin_tty = isatty(0); /* assume stdin is on fd 0 */
conf->tab_ok = TRUE; /* assume internactive default */
if (want_defhelp) { if (want_defhelp) {
givehelp(DEFAULTCALCHELP); givehelp(DEFAULTCALCHELP);
libcalc_call_me_last(); libcalc_call_me_last();
@@ -212,21 +223,12 @@ main(int argc, char **argv)
/* /*
* if allowed or needed, print version and setup bindings * if allowed or needed, print version and setup bindings
*/ */
if (interactive) { if (!havecommands && stdin_tty) {
/* if (!d_flag) {
* check for pipe mode and/or non-tty stdin
*/
if (!p_flag) {
stdin_tty = isatty(0); /* assume stdin is on fd 0 */
}
/*
* if tty, setup bindings
*/
if (stdin_tty) {
printf("%s (version %s)\n", CALC_TITLE, version()); printf("%s (version %s)\n", CALC_TITLE, version());
printf("[%s]\n\n", printf("[%s]\n\n",
"Type \"exit\" to exit, or \"help\" for help."); "Type \"exit\" to exit, or \"help\" for help.");
}
switch (hist_init(calcbindings)) { switch (hist_init(calcbindings)) {
case HIST_NOFILE: case HIST_NOFILE:
fprintf(stderr, fprintf(stderr,
@@ -242,7 +244,6 @@ main(int argc, char **argv)
break; break;
} }
} }
}
/* /*
* establish error longjump point with initial conditions * establish error longjump point with initial conditions
@@ -252,53 +253,82 @@ main(int argc, char **argv)
/* /*
* reset/initialize the computing environment * reset/initialize the computing environment
*/ */
if (post_init) { if (post_init)
initialize(); initialize();
} else {
/* initialize already done, jmpbuf is ready */
post_init = TRUE; post_init = TRUE;
} }
/* (void) signal(SIGINT, intint);
* if arg mode or non-tty mode, just do the work and be gone
*/
if (!interactive || !stdin_tty) {
if (q_flag == FALSE && allow_read) {
runrcfiles();
q_flag = TRUE;
}
if (interactive)
(void) openterminal();
else
(void) openstring(cmdbuf);
start_done = TRUE;
getcommands(FALSE);
libcalc_call_me_last();
exit(0);
}
}
/* if in arg mode, we should not get here */
if (!interactive) {
libcalc_call_me_last();
exit(1);
}
/* if (start_done == 0) {
* process commands if (!q_flag && allow_read) {
*/ start_done = 1;
if (!start_done) { runrcfiles();
}
start_done = 2;
}
if (start_done == 1) {
fprintf(stderr, "Execution error in rcfiles\n");
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE);
start_done = 2;
} else {
if ((havecommands && !i_flag) || !stdin_tty)
start_done = 7;
else if (havecommands)
start_done = 4;
else
start_done = 2;
}
}
if (start_done == 2) {
if (havecommands) {
start_done = 3;
(void) openstring(cmdbuf);
getcommands(FALSE);
}
start_done = 4;
}
if (start_done == 3) {
fprintf(stderr, "Execution error in commands\n");
if ((c_flag && !stoponerror) || stoponerror < 0) {
getcommands(FALSE);
start_done = 4;
}
else {
closeinput();
if (!stdin_tty || !i_flag)
start_done = 7;
else
start_done = 4;
}
}
if (start_done == 4) {
if (stdin_tty && ((havecommands && !i_flag) || p_flag))
start_done = 6;
else
openterminal();
}
else if (start_done == 5) {
if (!stdin_tty && (!c_flag || stoponerror) && stoponerror >= 0) {
start_done = 7;
}
else if ((c_flag && !stoponerror) || stoponerror < 0)
getcommands(FALSE);
else
reinitialize(); reinitialize();
} }
(void) signal(SIGINT, intint);
start_done = TRUE; if (start_done < 6) {
start_done = 5;
getcommands(TRUE); getcommands(TRUE);
}
/* /*
* all done * all done
*/ */
libcalc_call_me_last(); libcalc_call_me_last();
/* exit(0); */ return (start_done - 6) ? 1 : 0;
return 0;
} }

4
calc.h
View File

@@ -58,6 +58,8 @@
#define ABORT_MATH 3 /* abort on any math operation */ #define ABORT_MATH 3 /* abort on any math operation */
#define ABORT_NOW 4 /* abort right away */ #define ABORT_NOW 4 /* abort right away */
#define ERRMAX 20 /* default errmax value */
/* /*
* File ids corresponding to standard in, out, error, and when not in use. * File ids corresponding to standard in, out, error, and when not in use.
*/ */
@@ -163,7 +165,7 @@ extern char *shell; /* $SHELL or default */
extern char *program; /* our name (argv[0]) */ extern char *program; /* our name (argv[0]) */
extern int no_env; /* TRUE (-e) => ignore env vars on startup */ extern int no_env; /* TRUE (-e) => ignore env vars on startup */
extern int ign_errmax; /* TRUE (-i) => ignore when errcount exceeds errmax */ extern int errmax; /* if >= 0, error when errcount exceeds errmax */
extern int new_std; /* TRUE (-n) => use newstd configuration */ extern int new_std; /* TRUE (-n) => use newstd configuration */
extern int allow_read; /* FALSE => may not open any files for reading */ extern int allow_read; /* FALSE => may not open any files for reading */

View File

@@ -261,6 +261,8 @@ getfunction(void)
{ {
char *name; /* parameter name */ char *name; /* parameter name */
int type; /* type of token read */ int type; /* type of token read */
LABEL label;
long index;
(void) tokenmode(TM_DEFAULT); (void) tokenmode(TM_DEFAULT);
if (gettoken() != T_SYMBOL) { if (gettoken() != T_SYMBOL) {
@@ -276,9 +278,11 @@ getfunction(void)
beginfunc(name, FALSE); beginfunc(name, FALSE);
enterfuncscope(); enterfuncscope();
if (gettoken() != T_LEFTPAREN) { if (gettoken() != T_LEFTPAREN) {
scanerror(T_SEMICOLON, "Left parenthesis expected for function"); scanerror(T_SEMICOLON,
"Left parenthesis expected for function");
return; return;
} }
index = 0;
for (;;) { for (;;) {
type = gettoken(); type = gettoken();
if (type == T_RIGHTPAREN) if (type == T_RIGHTPAREN)
@@ -292,12 +296,22 @@ getfunction(void)
case SYM_UNDEFINED: case SYM_UNDEFINED:
case SYM_GLOBAL: case SYM_GLOBAL:
case SYM_STATIC: case SYM_STATIC:
(void) addparam(name); index = addparam(name);
break; break;
default: default:
scanerror(T_NULL, "Parameter \"%s\" is already defined", name); scanerror(T_NULL, "Parameter \"%s\" is already defined", name);
} }
type = gettoken(); type = gettoken();
if (type == T_ASSIGN) {
clearlabel(&label);
addopone(OP_PARAMADDR, index);
addoplabel(OP_JUMPNN, &label);
getopassignment();
addop(OP_ASSIGNPOP);
setlabel(&label);
type = gettoken();
}
if (type == T_RIGHTPAREN) if (type == T_RIGHTPAREN)
break; break;
if (type != T_COMMA) { if (type != T_COMMA) {
@@ -598,25 +612,25 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
scanerror(T_SEMICOLON, "CONTINUE not within FOR, WHILE, or DO"); scanerror(T_SEMICOLON, "CONTINUE not within FOR, WHILE, or DO");
return; return;
} }
addoplabel(OP_JUMPNE, contlabel); addoplabel(OP_JUMPNZ, contlabel);
break; break;
case T_BREAK: case T_BREAK:
if (breaklabel == NULL_LABEL) { if (breaklabel == NULL_LABEL) {
scanerror(T_SEMICOLON, "BREAK not within FOR, WHILE, or DO"); scanerror(T_SEMICOLON, "BREAK not within FOR, WHILE, or DO");
return; return;
} }
addoplabel(OP_JUMPNE, breaklabel); addoplabel(OP_JUMPNZ, breaklabel);
break; break;
case T_GOTO: case T_GOTO:
if (gettoken() != T_SYMBOL) { if (gettoken() != T_SYMBOL) {
scanerror(T_SEMICOLON, "Missing label in goto"); scanerror(T_SEMICOLON, "Missing label in goto");
return; return;
} }
addop(OP_JUMPNE); addop(OP_JUMPNZ);
addlabel(tokensymbol()); addlabel(tokensymbol());
break; break;
default: default:
addoplabel(OP_JUMPEQ, &label1); addoplabel(OP_JUMPZ, &label1);
rescantoken(); rescantoken();
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL); getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
if (gettoken() != T_ELSE) { if (gettoken() != T_ELSE) {
@@ -667,7 +681,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
contlabel = &label1; contlabel = &label1;
rescantoken(); rescantoken();
(void) getexprlist(); (void) getexprlist();
addoplabel(OP_JUMPNE, &label3); addoplabel(OP_JUMPNZ, &label3);
addoplabel(OP_JUMP, breaklabel); addoplabel(OP_JUMP, breaklabel);
if (gettoken() != T_SEMICOLON) { if (gettoken() != T_SEMICOLON) {
(void) tokenmode(oldmode); (void) tokenmode(oldmode);
@@ -708,7 +722,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
clearlabel(breaklabel); clearlabel(breaklabel);
setlabel(contlabel); setlabel(contlabel);
getcondition(); getcondition();
addoplabel(OP_JUMPEQ, breaklabel); addoplabel(OP_JUMPZ, breaklabel);
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL); getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
addoplabel(OP_JUMP, contlabel); addoplabel(OP_JUMP, contlabel);
setlabel(breaklabel); setlabel(breaklabel);
@@ -731,7 +745,7 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
} }
setlabel(contlabel); setlabel(contlabel);
getcondition(); getcondition();
addoplabel(OP_JUMPNE, &label3); addoplabel(OP_JUMPNZ, &label3);
setlabel(breaklabel); setlabel(breaklabel);
(void) tokenmode(oldmode); (void) tokenmode(oldmode);
return; return;
@@ -815,6 +829,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
printeol = TRUE; printeol = TRUE;
for (;;) { for (;;) {
switch (gettoken()) { switch (gettoken()) {
case T_RIGHTPAREN:
case T_RIGHTBRACKET:
case T_RIGHTBRACE: case T_RIGHTBRACE:
case T_NEWLINE: case T_NEWLINE:
case T_EOF: case T_EOF:
@@ -1377,6 +1393,21 @@ getassignment (void)
{ {
int type; /* type of expression */ int type; /* type of expression */
switch(gettoken()) {
case T_COMMA:
case T_SEMICOLON:
case T_NEWLINE:
case T_RIGHTPAREN:
case T_RIGHTBRACKET:
case T_RIGHTBRACE:
case T_EOF:
addop(OP_UNDEF);
rescantoken();
return EXPR_RVALUE;
}
rescantoken();
type = getaltcond(); type = getaltcond();
switch (gettoken()) { switch (gettoken()) {
@@ -1441,7 +1472,7 @@ getaltcond(void)
} }
clearlabel(&donelab); clearlabel(&donelab);
clearlabel(&altlab); clearlabel(&altlab);
addoplabel(OP_JUMPEQ, &altlab); addoplabel(OP_JUMPZ, &altlab);
type = getaltcond(); type = getaltcond();
if (gettoken() != T_COLON) { if (gettoken() != T_COLON) {
scanerror(T_SEMICOLON, "Missing colon for conditional expression"); scanerror(T_SEMICOLON, "Missing colon for conditional expression");

View File

@@ -85,7 +85,7 @@
/* /*
* config defult symbols * config default symbols
*/ */
#define DISPLAY_DEFAULT 20 /* default digits for float display */ #define DISPLAY_DEFAULT 20 /* default digits for float display */
#define EPSILON_DEFAULT "1e-20" /* allowed error for float calculations */ #define EPSILON_DEFAULT "1e-20" /* allowed error for float calculations */
@@ -95,8 +95,6 @@
#define MAXPRINT_DEFAULT 16 /* default number of elements printed */ #define MAXPRINT_DEFAULT 16 /* default number of elements printed */
#define MAXSCANCOUNT 20 /* default max scan errors before an abort */ #define MAXSCANCOUNT 20 /* default max scan errors before an abort */
#define ERRMAX 20 /* default errmax value */
/* /*
* configuration object * configuration object

76
func.c
View File

@@ -84,6 +84,8 @@ extern void matrandperm(MATRIX *M);
extern void listrandperm(LIST *lp); extern void listrandperm(LIST *lp);
extern int idungetc(FILEID id, int ch); extern int idungetc(FILEID id, int ch);
extern int stoponerror;
/* /*
* if HZ & CLK_TCK are not defined, pick typical values, hope for the best * if HZ & CLK_TCK are not defined, pick typical values, hope for the best
@@ -209,6 +211,28 @@ f_prompt(VALUE *vp)
} }
static VALUE
f_display(int count, VALUE **vals)
{
long oldvalue;
VALUE res;
oldvalue = conf->outdigits;
if (count > 0) {
if (vals[0]->v_type != V_NUM || qisfrac(vals[0]->v_num) ||
qisneg(vals[0]->v_num) || zge31b(vals[0]->v_num->num))
fprintf(stderr,
"Out-of-range arg for display ignored\n");
else
conf->outdigits = qtoi(vals[0]->v_num);
}
res.v_type = V_NUM;
res.v_num = itoq(oldvalue);
return res;
}
/*ARGSUSED*/ /*ARGSUSED*/
static VALUE static VALUE
f_null(int count, VALUE **vals) f_null(int count, VALUE **vals)
@@ -4392,11 +4416,7 @@ f_errno(int count, VALUE **vals)
math_error("errno argument out of range"); math_error("errno argument out of range");
/*NOTREACHED*/ /*NOTREACHED*/
} }
newerr = z1tol(vp->v_num->num); newerr = (int) ztoi(vp->v_num->num);
if (newerr >= 32768) {
math_error("errno argument out of range");
/*NOTREACHED*/
}
} }
olderr = set_errno(newerr); olderr = set_errno(newerr);
@@ -4423,7 +4443,7 @@ f_errcount(int count, VALUE **vals)
math_error("errcount argument out of range"); math_error("errcount argument out of range");
/*NOTREACHED*/ /*NOTREACHED*/
} }
newcount = z1tol(vp->v_num->num); newcount = (int) ztoi(vp->v_num->num);
} }
oldcount = set_errcount(newcount); oldcount = set_errcount(newcount);
@@ -4436,23 +4456,21 @@ f_errcount(int count, VALUE **vals)
static VALUE static VALUE
f_errmax(int count, VALUE **vals) f_errmax(int count, VALUE **vals)
{ {
int newmax, oldmax; int oldmax;
VALUE *vp; VALUE *vp;
VALUE result; VALUE result;
newmax = -1; oldmax = errmax;
if (count > 0) { if (count > 0) {
vp = vals[0]; vp = vals[0];
/* arg must be an integer */
if (vp->v_type != V_NUM || qisfrac(vp->v_num) || if (vp->v_type != V_NUM || qisfrac(vp->v_num) ||
qisneg(vp->v_num) || zge31b(vp->v_num->num)) { zge31b(vp->v_num->num))
math_error("errcount argument out of range"); fprintf(stderr,
/*NOTREACHED*/ "Out-of-range arg for errmax ignored\n");
else
errmax = (int) ztoi(vp->v_num->num);
} }
newmax = z1tol(vp->v_num->num);
}
oldmax = set_errmax(newmax);
result.v_type = V_NUM; result.v_type = V_NUM;
result.v_num = itoq((long) oldmax); result.v_num = itoq((long) oldmax);
@@ -4460,6 +4478,30 @@ f_errmax(int count, VALUE **vals)
} }
static VALUE
f_stoponerror(int count, VALUE **vals)
{
int oldval;
VALUE *vp;
VALUE result;
oldval = stoponerror;
if (count > 0) {
vp = vals[0];
if (vp->v_type != V_NUM || qisfrac(vp->v_num) ||
zge31b(vp->v_num->num))
fprintf(stderr,
"Out-of-range arg for stoponerror ignored\n");
else
stoponerror = (int) ztoi(vp->v_num->num);
}
result.v_type = V_NUM;
result.v_num = itoq((long) oldval);
return result;
}
static VALUE static VALUE
f_fclose(int count, VALUE **vals) f_fclose(int count, VALUE **vals)
{ {
@@ -6806,6 +6848,8 @@ static CONST struct builtin builtins[] = {
"digit at specified decimal place of number"}, "digit at specified decimal place of number"},
{"digits", 1, 1, 0, OP_NOP, f_digits, 0, {"digits", 1, 1, 0, OP_NOP, f_digits, 0,
"number of digits in number"}, "number of digits in number"},
{"display", 0, 1, 0, OP_NOP, 0, f_display,
"number of decimal digits for displaying numbers"},
{"dp", 2, 2, 0, OP_NOP, 0, f_dp, {"dp", 2, 2, 0, OP_NOP, 0, f_dp,
"dot product of two vectors"}, "dot product of two vectors"},
{"epsilon", 0, 1, 0, OP_SETEPSILON, 0, 0, {"epsilon", 0, 1, 0, OP_SETEPSILON, 0, 0,
@@ -7188,6 +7232,8 @@ static CONST struct builtin builtins[] = {
"seed the random() function"}, "seed the random() function"},
{"ssq", 1, IN, 0, OP_NOP, 0, f_ssq, {"ssq", 1, IN, 0, OP_NOP, 0, f_ssq,
"sum of squares of values"}, "sum of squares of values"},
{"stoponerror", 0, 1, 0, OP_NOP, 0, f_stoponerror,
"assign value to stoponerror flag"},
{"str", 1, 1, 0, OP_NOP, 0, f_str, {"str", 1, 1, 0, OP_NOP, 0, f_str,
"simple value converted to string"}, "simple value converted to string"},
{"strcat", 1,IN, 0, OP_NOP, 0, f_strcat, {"strcat", 1,IN, 0, OP_NOP, 0, f_strcat,

View File

@@ -44,7 +44,7 @@ CALC_FILES= README bigprime.cal deg.cal ellip.cal lucas.cal lucas_chk.cal \
test2700.cal test3100.cal test3300.cal test3400.cal prompt.cal \ test2700.cal test3100.cal test3300.cal test3400.cal prompt.cal \
test3500.cal seedrandom.cal test4000.cal test4100.cal test4600.cal \ test3500.cal seedrandom.cal test4000.cal test4100.cal test4600.cal \
beer.cal hello.cal test5100.cal test5200.cal randombitrun.cal \ beer.cal hello.cal test5100.cal test5200.cal randombitrun.cal \
randomrun.cal xx_print.cal natnumset.cal randomrun.cal xx_print.cal natnumset.cal qtime.cal
# These files are found (but not built) in the distribution # These files are found (but not built) in the distribution
# #

View File

@@ -311,6 +311,13 @@ psqrt.cal
Calculate square roots modulo a prime Calculate square roots modulo a prime
qtime.cal
qtime(utc_hr_offset)
Print the time as English sentence given the hours offset from UTC.
quat.cal quat.cal
quat(a, b, c, d) quat(a, b, c, d)

60
lib/qtime.cal Normal file
View File

@@ -0,0 +1,60 @@
/*
* qtime - Display time as English sentence
*
* usage:
* qtime(utc_hr_offset)
*
* utc_hr_offset Offset from UTC in hours.
*
* Written by: Klaus Alexander Seistrup <kseis@magnetic-ink.dk>
* With minor mods by: Landon Curt Noll <chongo@toad.com>
*
* See:
* http://www.magnetic-ink.dk/download/qtime.html
*
* for examples of qtime() written on other languages.
*/
/*
* qtime - Display time as English sentence
*/
define qtime(utc_hr_offset)
{
static mat hr[12] = {
"twelve", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten", "eleven"
};
static mat mn[7] = {
"", "five ", "ten ", "a quarter ", "twenty ", "twenty-five ", "half "
};
static mat ny[5] = {
"nearly ", "almost ", "", "just after ", "after "
};
static mat up[3] = {
"to ", "", "past "
};
local adj_mins = (((time() + utc_hr_offset*3600) % 86400) + 30) // 60 + 27;
local hours = (adj_mins // 60) % 12;
local minutes = adj_mins % 60;
local almost = minutes % 5;
local divisions = (minutes // 5) - 5;
local to_past_idx = divisions > 0 ? 1 : 0;
if (divisions < 0) {
divisions = -divisions;
to_past_idx = -1;
}
++to_past_idx;
/*
* Print the English sentence
*
* We avoid forward and back quotes just to show that the char()
* builtin function can be used in conjunction with a printf.
*/
printf("It%cs %s%s%s%s",
char(0x27), ny[almost], mn[divisions], up[to_past_idx], hr[hours]);
if (divisions == 0)
printf(" o%cclock", char(0x27));
printf (".\n");
}

View File

@@ -22,7 +22,7 @@ prob = 0; /* clear problem counter */
global junk; /* throw away value */ global junk; /* throw away value */
junk = errcount(0); /* clear error count */ junk = errcount(0); /* clear error count */
junk = errmax(0x7fffffff); /* set maximum error very high */ junk = errmax(-1); /* prevent errcount from abouting */
global ecnt; /* expected value of errcount() */ global ecnt; /* expected value of errcount() */
ecnt = 0; /* clear expected errcount() value */ ecnt = 0; /* clear expected errcount() value */
@@ -7468,7 +7468,9 @@ read -once unitfrac;
print '9826: read -once unitfrac'; print '9826: read -once unitfrac';
read -once varargs; read -once varargs;
print '9827: read -once varargs'; print '9827: read -once varargs';
print '9828: Ending read of selected calc libs'; read -once qtime;
print '9828: read -once qtime';
print '9829: Ending read of selected calc libs';
/* /*

View File

@@ -82,7 +82,9 @@ int allow_exec = TRUE; /* FALSE => may not execute any commands */
int p_flag = FALSE; /* TRUE => pipe mode */ int p_flag = FALSE; /* TRUE => pipe mode */
int q_flag = FALSE; /* TRUE => don't execute rc files */ int q_flag = FALSE; /* TRUE => don't execute rc files */
int u_flag = FALSE; /* TRUE => unbuffer stdin and stdout */ int u_flag = FALSE; /* TRUE => unbuffer stdin and stdout */
int d_flag = FALSE; /* TRUE => disable heading, lib_debug == 0 */
int stoponerror = FALSE; /* >0 => stop, <0 => continue on error */
/* /*
* global values * global values
@@ -98,7 +100,7 @@ int interactive = FALSE; /* TRUE if interactive session (no cmd args) */
int post_init = FALSE; /* TRUE setjmp for math_error is readready */ int post_init = FALSE; /* TRUE setjmp for math_error is readready */
int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */ int no_env = FALSE; /* TRUE (-e) => ignore env vars on startup */
int ign_errmax = FALSE; /* TRUE (-i) => ignore when errcount exceeds errmax */ int errmax = ERRMAX; /* if >= 0, maximum value for errcount */
NUMBER *epsilon_default; /* default allowed error for float calcs */ NUMBER *epsilon_default; /* default allowed error for float calcs */
@@ -155,6 +157,13 @@ libcalc_call_me_first(void)
conf = config_copy(&oldstd); conf = config_copy(&oldstd);
} }
/*
* -d turns off lib_debug
*/
if (d_flag) {
conf->lib_debug = 0;
}
/* /*
* initialize * initialize
*/ */
@@ -229,10 +238,6 @@ reinitialize(void)
math_setfp(stdout); math_setfp(stdout);
resetscopes(); resetscopes();
resetinput(); resetinput();
if (q_flag == FALSE && allow_read) {
q_flag = TRUE;
runrcfiles();
}
(void) openterminal(); (void) openterminal();
} }

View File

@@ -32,7 +32,6 @@ static VALUE oldvalue; /* previous calculation value */
static BOOL saveval = TRUE; /* to enable or disable saving */ static BOOL saveval = TRUE; /* to enable or disable saving */
static int calc_errno; /* most recent error-number */ static int calc_errno; /* most recent error-number */
static int errcount; /* counts calls to error_value */ static int errcount; /* counts calls to error_value */
static int errmax = ERRMAX; /* maximum for errcount without abort */
static BOOL go; static BOOL go;
/* /*
@@ -2467,7 +2466,7 @@ o_return(void)
/*ARGSUSED*/ /*ARGSUSED*/
static void static void
o_jumpeq(FUNC *fp, BOOL *dojump) o_jumpz(FUNC *fp, BOOL *dojump)
{ {
VALUE *vp; VALUE *vp;
int i; /* result of comparison */ int i; /* result of comparison */
@@ -2491,7 +2490,7 @@ o_jumpeq(FUNC *fp, BOOL *dojump)
/*ARGSUSED*/ /*ARGSUSED*/
static void static void
o_jumpne(FUNC *fp, BOOL *dojump) o_jumpnz(FUNC *fp, BOOL *dojump)
{ {
VALUE *vp; VALUE *vp;
int i; /* result of comparison */ int i; /* result of comparison */
@@ -2513,6 +2512,20 @@ o_jumpne(FUNC *fp, BOOL *dojump)
} }
/*
* jumpnn invokes a jump if top value points to a null value
*/
/*ARGSUSED*/
static void
o_jumpnn(FUNC *fp, BOOL *dojump)
{
if (stack->v_addr->v_type) {
*dojump = TRUE;
stack--;
}
}
/*ARGSUSED*/ /*ARGSUSED*/
static void static void
o_condorjump(FUNC *fp, BOOL *dojump) o_condorjump(FUNC *fp, BOOL *dojump)
@@ -3111,7 +3124,8 @@ o_quit(FUNC *fp, long index)
s = findstring(index); s = findstring(index);
cp = s->s_str; cp = s->s_str;
} }
if ((fp->f_name[0] == '*') && (fp->f_name[1] == '\0')) { if (inputisterminal() && (fp->f_name[0] == '*')
&& (fp->f_name[1] == '\0')) {
if (cp) if (cp)
printf("%s\n", cp); printf("%s\n", cp);
hist_term(); hist_term();
@@ -3126,6 +3140,8 @@ o_quit(FUNC *fp, long index)
printf("%s\n", cp); printf("%s\n", cp);
else else
printf("Quit statement executed\n"); printf("Quit statement executed\n");
if (!inputisterminal() && fp->f_name[0] == '*')
closeinput();
go = FALSE; go = FALSE;
} }
@@ -3243,7 +3259,7 @@ error_value(int e)
calc_errno = e; calc_errno = e;
if (e > 0) if (e > 0)
errcount++; errcount++;
if (errcount > errmax && !ign_errmax) { if (errmax >= 0 && errcount > errmax) {
math_error("Error %d caused errcount to exceed errmax", e); math_error("Error %d caused errcount to exceed errmax", e);
/*NOTREACHED*/ /*NOTREACHED*/
} }
@@ -3281,21 +3297,6 @@ set_errcount(int e)
} }
/*
* set_errno - return and set errno
*/
int
set_errmax(int e)
{
int res;
res = errmax;
if (e >= 0)
errmax = e;
return res;
}
/* /*
* Fill a newly created matrix at v1 with copies of value at v2. * Fill a newly created matrix at v1 with copies of value at v2.
*/ */
@@ -3427,8 +3428,8 @@ static struct opcode opcodes[MAX_OPCODE+1] = {
{o_duplicate, OPNUL, "DUPLICATE"}, /* duplicate top value */ {o_duplicate, OPNUL, "DUPLICATE"}, /* duplicate top value */
{o_pop, OPNUL, "POP"}, /* pop top value */ {o_pop, OPNUL, "POP"}, /* pop top value */
{o_return, OPRET, "RETURN"}, /* return value of function */ {o_return, OPRET, "RETURN"}, /* return value of function */
{o_jumpeq, OPJMP, "JUMPEQ"}, /* jump if value zero */ {o_jumpz, OPJMP, "JUMPZ"}, /* jump if value zero */
{o_jumpne, OPJMP, "JUMPNE"}, /* jump if value nonzero */ {o_jumpnz, OPJMP, "JUMPNZ"}, /* jump if value nonzero */
{o_jump, OPJMP, "JUMP"}, /* jump unconditionally */ {o_jump, OPJMP, "JUMP"}, /* jump unconditionally */
{o_usercall, OPTWO, "USERCALL"}, /* call a user function */ {o_usercall, OPTWO, "USERCALL"}, /* call a user function */
{o_getvalue, OPNUL, "GETVALUE"}, /* convert address to value */ {o_getvalue, OPNUL, "GETVALUE"}, /* convert address to value */
@@ -3531,7 +3532,8 @@ static struct opcode opcodes[MAX_OPCODE+1] = {
{o_hashop, OPNUL, "HASHOP"}, /* binary hash op */ {o_hashop, OPNUL, "HASHOP"}, /* binary hash op */
{o_backslash, OPNUL, "BACKSLASH"}, /* unary backslash op */ {o_backslash, OPNUL, "BACKSLASH"}, /* unary backslash op */
{o_setminus, OPNUL, "SETMINUS"}, /* binary backslash op */ {o_setminus, OPNUL, "SETMINUS"}, /* binary backslash op */
{o_plus, OPNUL, "PLUS"} /* unary + op */ {o_plus, OPNUL, "PLUS"}, /* unary + op */
{o_jumpnn, OPJMP, "JUMPNN"} /* jump if non-null */
}; };
@@ -3695,6 +3697,7 @@ calculate(FUNC *fp, int argcount)
freevalue(&locals[i]); freevalue(&locals[i]);
if (locals != localtable) if (locals != localtable)
free(locals); free(locals);
if (conf->calc_debug & 2)
printf("\t\"%s\": line %ld\n", funcname, funcline); printf("\t\"%s\": line %ld\n", funcname, funcline);
while (stack > beginstack) while (stack > beginstack)
freevalue(stack--); freevalue(stack--);
@@ -3751,11 +3754,11 @@ dumpop(unsigned long *pc)
case OP_INDEXADDR: case OP_INDEXADDR:
printf(" %ld %ld\n", pc[0], pc[1]); printf(" %ld %ld\n", pc[0], pc[1]);
return 3; return 3;
case OP_PRINT: case OP_JUMPEQ: case OP_JUMPNE: case OP_JUMP: case OP_PRINT: case OP_JUMPZ: case OP_JUMPNZ: case OP_JUMP:
case OP_CONDORJUMP: case OP_CONDANDJUMP: case OP_CASEJUMP: case OP_CONDORJUMP: case OP_CONDANDJUMP: case OP_CASEJUMP:
case OP_INITSTATIC: case OP_MATCREATE: case OP_OBJCREATE: case OP_INITSTATIC: case OP_MATCREATE: case OP_OBJCREATE:
case OP_SHOW: case OP_ELEMINIT: case OP_ELEMADDR: case OP_SHOW: case OP_ELEMINIT: case OP_ELEMADDR:
case OP_ELEMVALUE: case OP_ELEMVALUE: case OP_JUMPNN:
printf(" %ld\n", *pc); printf(" %ld\n", *pc);
return 2; return 2;
case OP_NUMBER: case OP_IMAGINARY: case OP_NUMBER: case OP_IMAGINARY:

View File

@@ -38,8 +38,8 @@
#define OP_DUPLICATE 23L /* duplicate top value on stack */ #define OP_DUPLICATE 23L /* duplicate top value on stack */
#define OP_POP 24L /* pop top value from stack */ #define OP_POP 24L /* pop top value from stack */
#define OP_RETURN 25L /* return value of function */ #define OP_RETURN 25L /* return value of function */
#define OP_JUMPEQ 26L /* jump if top value is zero */ #define OP_JUMPZ 26L /* jump if top value is zero */
#define OP_JUMPNE 27L /* jump if top value is nonzero */ #define OP_JUMPNZ 27L /* jump if top value is nonzero */
#define OP_JUMP 28L /* jump unconditionally */ #define OP_JUMP 28L /* jump unconditionally */
#define OP_USERCALL 29L /* call a user-defined function */ #define OP_USERCALL 29L /* call a user-defined function */
#define OP_GETVALUE 30L /* convert address to value */ #define OP_GETVALUE 30L /* convert address to value */
@@ -143,7 +143,8 @@
#define OP_BACKSLASH 128L /* unary backslash */ #define OP_BACKSLASH 128L /* unary backslash */
#define OP_SETMINUS 129L /* binary backslash */ #define OP_SETMINUS 129L /* binary backslash */
#define OP_PLUS 130L /* unary + */ #define OP_PLUS 130L /* unary + */
#define MAX_OPCODE 130L /* highest legal opcode */ #define OP_JUMPNN 131L /* jump if top value is non-null */
#define MAX_OPCODE 131L /* highest legal opcode */
/* /*

View File

@@ -213,7 +213,6 @@ extern BOOL precvalue(VALUE *v1, VALUE *v2);
extern VALUE error_value(int e); extern VALUE error_value(int e);
extern int set_errno(int e); extern int set_errno(int e);
extern int set_errcount(int e); extern int set_errcount(int e);
extern int set_errmax(int e);
extern long countlistitems(LIST *lp); extern long countlistitems(LIST *lp);
extern void addlistitems(LIST *lp, VALUE *vres); extern void addlistitems(LIST *lp, VALUE *vres);
extern void addlistinv(LIST *lp, VALUE *vres); extern void addlistinv(LIST *lp, VALUE *vres);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997 David I. Bell * Copyright (c) 1999 David I. Bell
* Permission is granted to use, distribute, or modify this source, * Permission is granted to use, distribute, or modify this source,
* provided that this copyright notice remains intact. * provided that this copyright notice remains intact.
* *
@@ -12,7 +12,7 @@
#define MAJOR_VER 2 /* major version */ #define MAJOR_VER 2 /* major version */
#define MINOR_VER 11 /* minor version */ #define MINOR_VER 11 /* minor version */
#define MAJOR_PATCH 0 /* patch level or 0 if no patch */ #define MAJOR_PATCH 0 /* patch level or 0 if no patch */
#define MINOR_PATCH "6.3" /* test number or empty string if no patch */ #define MINOR_PATCH "7.1" /* test number or empty string if no patch */
/* /*
* calc version constants * calc version constants
@@ -80,7 +80,3 @@ version(void)
*/ */
return stored_version; return stored_version;
} }
/* END CODE */