Jeffrey E Altman <jaltman@secure-endpoints.com>
Secure Endpoints Inc., New York City
- Copyright (C) 1985, 2009,
+ Copyright (C) 1985, 2011,
Trustees of Columbia University in the City of New York.
All rights reserved. See the C-Kermit COPYING.TXT file or the
copyright text in the ckcmai.c module for disclaimer and permissions.
"eval", SX_EVA, 0, /* Assorted commands */
"abs", SX_ABS, SXF_ONE,
"truncate",SX_TRU, SXF_ONE|SXF_FLO,
- "round", SX_ROU, SXF_ONE|SXF_FLO,
+ "round", SX_ROU, SXF_ONE|SXF_TWO|SXF_FLO,
"ceiling", SX_CEI, SXF_ONE|SXF_FLO,
"floor", SX_FLR, SXF_ONE|SXF_FLO,
"float", SX_FLO, SXF_ONE|SXF_FLO,
#include <math.h> /* Floating-point functions */
_PROTOTYP( char * fpformat, (CKFLOAT, int, int) );
+_PROTOTYP( CKFLOAT ckround, (CKFLOAT, int, char *, int) );
extern char math_pi[]; /* Value of Pi */
extern int sexpecho; /* SET SEXPRESSION ECHO value */
/* Returns value as string (empty, numeric, or non-numeric) */
+static char sxroundbuf[32]; /* For ROUND result */
+
char *
dosexp(s) char *s; { /* s = S-Expression */
extern struct mtab *mactab; /* Macro table */
}
/* Break result up into "words" (an SEXP counts as a word) */
- p[0] = NULL; /* (We don't use element 0) */
+ for (i = 0; i < SEXPMAX+1; i++ ) { /* Clear the operands */
+ p[i] = NULL;
+ }
if (!*(s+1) || !*(s+2)) { /* No need to call cksplit() */
n = 1; /* if it's one or two chars. */
p[1] = s; /* No need to malloc this either. */
debug(F110,sexpdebug("head"),p[1],0);
if (n == 1 && p[1]) {
- if (*(p[1]) == '\047') {
+ if (*(p[1]) == '\047') { /* Apostrophe = LISP quote character */
s2 = p[1];
goto xdosexp;
}
}
break;
case SXF_ONE:
- if (n != 2) {
+ if (n != 2) {
printf("?Too %s operands - \"%s\"\n",
(n > 2) ? "many" : "few", s);
sexprc++;
}
if (kwflags & SXF_FLO) /* Operator requires floating point */
fpflag++; /* Force it */
+
+ if (x == SX_ROU) { /* ROUND can have 1 or 2 arguments */
+ if (n < 2 || n > 3) {
+ printf("?Too %s operands - \"%s\"\n",
+ (n > 3) ? "many" : "few", s);
+ sexprc++;
+ goto xdosexp;
+ }
+ }
+ if (x == SX_ROU) {
+ /* But they are not "cumulative" like other SEXP args */
+ /* So this case is handled specially */
+ char buf1[32], buf2[32];
+ float r;
+ char * s0, * s1;
+ char * q0, * q1;
+
+ s0 = p[2];
+ if (!s0) s0 = "";
+ if (!*s0) s0 = "0";
+ q0 = dosexp(s0);
+ ckstrncpy(buf1,q0,32);
+ q0 = buf1;
+
+ s1 = p[3];
+ if (!s1) s1 = "";
+ if (!*s1) s1 = "0";
+ q1 = dosexp(s1);
+ if (!q1) q1 = "";
+ if (!*q1) q1 = "0";
+ ckstrncpy(buf2,q1,32);
+ q1 = buf2;
+
+ r = ckround(atof(q0),(int)(atof(q1)),sxroundbuf,31);
+ s2 = sxroundbuf;
+ sexprc = 0;
+ goto xdosexp;
+ }
}
if (x == SX_SET || x == SX_LET || /* Assignment is special */
x == SX_INC || x == SX_DEC) {
quote = 0;
s2 = p[i+1]; /* Get operand */
if (!s2) s2 = "";
+
#ifdef COMMENT
if (*s2 == '\047') { /* Is it quoted? */
debug(F110,sexpdebug("'B"),s2,0);
if ((x == SX_AND && result == 0) || /* Short circuit */
(x == SX_LOR && result != 0))
quit++;
- if (!(kwflags & SXF_ONE)) /* Command with single arg */
+ if (!(kwflags & SXF_ONE)) /* Command w/single arg */
continue;
}
if (x == SX_MOD || x == SX_DIV) {
truncate = 1;
break;
- case SX_ROU: /* Round */
- if (fpj > 0.0)
- fpj += 0.5;
- else if (fpj < 0.0)
- fpj -= 0.5;
- fpresult = fpj;
- fpflag = 1;
- truncate = 1;
- break;
-
case SX_ABS: /* Absolute value */
result = (j < 0) ? 0 - j : j;
#ifdef FNFLOAT