"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/common/calculator.c" between
wcalc-2.4.1.tar.gz and wcalc-2.5.tar.gz

About: Wcalc is a natural-expression command-line calculator.

calculator.c  (wcalc-2.4.1):calculator.c  (wcalc-2.5)
skipping to change at line 12 skipping to change at line 12
# include "config.h" # include "config.h"
#else #else
# define HAVE_MPFR_22 # define HAVE_MPFR_22
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <math.h> /* for HUGE_VAL */ #include <math.h> /* for HUGE_VAL */
#include <float.h> /* for DBL_EPSILON */ #include <float.h> /* for DBL_EPSILON */
#include <ctype.h> /* for isalpha() */ #include <ctype.h> /* for isalpha() */
#include <assert.h>
#include "output.h"
#ifndef isnan #ifndef isnan
# define isnan(x) \ # define isnan(x) \
(sizeof(x) == sizeof(long double) ? isnan_ld(x) \ (sizeof(x) == sizeof(long double) ? isnan_ld(x) \
: sizeof(x) == sizeof(double) ? isnan_d(x) \ : sizeof(x) == sizeof(double) ? isnan_d(x) \
: isnan_f(x)) : isnan_f(x))
static inline int isnan_f (float x) static inline int
isnan_f(float x)
{ /*{{{*/ { /*{{{*/
return x != x; return x != x;
} /*}}}*/ } /*}}}*/
static inline int isnan_d (double x) static inline int
isnan_d(double x)
{ /*{{{*/ { /*{{{*/
return x != x; return x != x;
} /*}}}*/ } /*}}}*/
static inline int isnan_ld (long double x) static inline int
isnan_ld(long double x)
{ /*{{{*/ { /*{{{*/
return x != x; return x != x;
} /*}}}*/ } /*}}}*/
#endif /* ifndef isnan */ #endif /* ifndef isnan */
#ifndef isinf #ifndef isinf
# define isinf(x) \ # define isinf(x) \
(sizeof(x) == sizeof(long double) ? isinf_ld(x) \ (sizeof(x) == sizeof(long double) ? isinf_ld(x) \
: sizeof(x) == sizeof(double) ? isinf_d(x) \ : sizeof(x) == sizeof(double) ? isinf_d(x) \
: isinf_f(x)) : isinf_f(x))
static inline int isinf_f (float x) static inline int
isinf_f(float x)
{ /*{{{*/ { /*{{{*/
return isnan(x - x); return isnan(x - x);
} /*}}}*/ } /*}}}*/
static inline int isinf_d (double x) static inline int
isinf_d(double x)
{ /*{{{*/ { /*{{{*/
return isnan(x - x); return isnan(x - x);
} /*}}}*/ } /*}}}*/
static inline int isinf_ld (long double x) static inline int
isinf_ld(long double x)
{ /*{{{*/ { /*{{{*/
return isnan(x - x); return isnan(x - x);
} /*}}}*/ } /*}}}*/
#endif /* ifndef isinf */ #endif /* ifndef isinf */
#if !defined(HAVE_CONFIG_H) || HAVE_STRING_H #if !defined(HAVE_CONFIG_H) || HAVE_STRING_H
# include <string.h> /* for memset() */ # include <string.h> /* for memset() */
#else #else
# if !HAVE_STRCHR # if !HAVE_STRCHR
# define strchr index # define strchr index
# define strrchr rindex # define strrchr rindex
# endif # endif
char *strchr(), *strrchr(); char *strchr(), *strrchr();
skipping to change at line 99 skipping to change at line 106
/* variables everyone needs to get to */ /* variables everyone needs to get to */
Number last_answer; Number last_answer;
char *pretty_answer = NULL; char *pretty_answer = NULL;
/* communication with the parser */ /* communication with the parser */
char compute = 1; char compute = 1;
unsigned int sig_figs = UINT32_MAX; unsigned int sig_figs = UINT32_MAX;
/* communication with the frontend */ /* communication with the frontend */
char standard_output = 1; char standard_output = 1;
char not_all_displayed = 0; char not_all_displayed = 0;
char *pa = NULL; char *pa = NULL;
char *last_input = NULL;
struct _conf conf; struct _conf conf;
/* /*
* These are declared here because they're not in any header files. * These are declared here because they're not in any header files.
* yyparse() is declared with an empty argument list so that it is * yyparse() is declared with an empty argument list so that it is
* compatible with the generated C code from yacc/bison. * compatible with the generated C code from yacc/bison.
* These two lines are taken from http://www.bgw.org/tutorials/programming/c/lex _yacc/main.c * These two lines are taken from http://www.bgw.org/tutorials/programming/c/lex _yacc/main.c
*/ */
struct yy_buffer_state; struct yy_buffer_state;
extern int yyparse(void); extern int yyparse(void);
extern void *yy_scan_string(const char *); extern void *yy_scan_string(const char *);
extern void yy_delete_buffer(struct yy_buffer_state *); extern void yy_delete_buffer(struct yy_buffer_state *);
static int recursion(char *str); static int recursion(char *str);
static int find_recursion(char *); static int find_recursion(char *);
static int find_recursion_core(List); static int find_recursion_core(List);
static char *flatten(char *str); static char *flatten(char *str);
void parseme(const char *pthis) void
parseme(const char *pthis)
{ /*{{{ */ { /*{{{ */
extern int synerrors; extern int synerrors;
short numbers = 0; short numbers = 0;
char *sanitized; char *sanitized;
extern char *open_file; extern char *open_file;
synerrors = 0; synerrors = 0;
compute = 1; compute = 1;
sig_figs = UINT32_MAX; sig_figs = UINT32_MAX;
Dprintf("parsing: %s\n", pthis); Dprintf("parsing: %s\n", pthis);
sanitized = (char *)strdup(pthis); sanitized = (char *)strdup(pthis);
/* Save a copy of the input */
{
extern int show_line_numbers;
if (show_line_numbers) {
if (last_input) {
free(last_input);
}
last_input = strdup(pthis);
}
}
/* Convert to standard notation (american comma and period) if there are /* Convert to standard notation (american comma and period) if there are
* numbers */ * numbers */
// are there numbers? // are there numbers?
{ {
unsigned int i; unsigned int i;
for (i = 0; i < strlen(sanitized); ++i) { for (i = 0; i < strlen(sanitized); ++i) {
if (isdigit((int)(sanitized[i]))) { if (isdigit((int)(sanitized[i]))) {
numbers = 1; numbers = 1;
break; break;
skipping to change at line 219 skipping to change at line 239
yyparse(); yyparse();
yy_delete_buffer(yy); yy_delete_buffer(yy);
} }
if (open_file) { if (open_file) {
char *filename = open_file; char *filename = open_file;
int retval; int retval;
open_file = NULL; open_file = NULL;
Dprintf("open_file\n"); Dprintf("open_file\n");
retval = loadState(filename, 1); retval = loadState(filename, 1);
if (retval) { if (retval) {
report_error("Could not load file (%s).", report_error("Could not load file (%s).",
(char *)strerror(retval)); (char *)strerror(retval));
} }
} }
exiting: exiting:
/* exiting */ /* exiting */
free(sanitized); free(sanitized);
} /*}}} */ } /*}}} */
static size_t
find_alpha(const char *str)
{
const size_t len = strlen(str);
size_t i = 0;
while ((i < len) && str[i] && !isalpha((int)str[i])) {
switch (str[i]) {
case '\\':
do {
i++;
} while ((i < len) && str[i] && isalpha((int)str[i]));
break;
case '\'':
{
char *tailquote = strchr(str + i + 1, '\'');
if (tailquote == NULL) { return len; } else {
i = (tailquote) - (str);
}
break;
}
case '0':
switch (str[i + 1]) {
case 'b': case 'x': i += 2; break;
default: i++; break;
}
break;
default: i++; break;
}
}
return i;
}
static char *
evaluate_var(const char *varname,
struct answer *aptr)
{
struct answer a;
char *varvalue = NULL;
// if it's a variable, evaluate it
a = getvar_full(varname);
if (!a.err) { // it is a var
Number f;
num_init(f);
if (a.exp) { // it is an expression
parseme(a.exp);
num_set(f, last_answer);
} else { // it is a value
num_set(f, a.val);
num_free(a.val);
}
// get the number
{
char junk;
// This value must fully reproduce the contents of f (thus, the -2 i
n arg 4)
varvalue = num_to_str_complex(f, 10, 0, -2, 1, &junk);
}
num_free(f);
} else { // not a known var: itza literal (e.g. cos)
varvalue = (char *)strdup(varname);
}
*aptr = a;
assert(varvalue != NULL);
return varvalue;
}
static char *
extract_var(char *str,
size_t *len)
{
const size_t max = strlen(str);
size_t i = 0;
char *var;
while (i < max &&
(isalpha((int)str[i]) || str[i] == '_' ||
str[i] == ':' || isdigit((int)str[i]))) {
i++;
}
if (i == 0) {
return NULL;
}
var = malloc((i + 1) * sizeof(char));
memcpy(var, str, i);
var[i] = 0;
if (len) { *len = i; }
return var;
}
/* this function should probably stop flattening if it sees a comment, but /* this function should probably stop flattening if it sees a comment, but
* that's so rare (and hardly processor intensive) that it's not worth digging * that's so rare (and hardly processor intensive) that it's not worth digging
* at the moment */ * at the moment */
static char *flatten(char *str) static char *
flatten(char *str)
{ /*{{{ */ { /*{{{ */
char *curs = str, *eov, *nstr; char *curs = str, *eov, *nstr;
char *varname, *varvalue; char *varname, *varvalue;
size_t olen, nlen, changedlen, varnamelen = 100; size_t changedlen;
struct answer a; struct answer a;
char standard_output_save = standard_output; char standard_output_save = standard_output;
standard_output = 0; standard_output = 0;
if (*str == '\\') { if (*str == '\\') {
standard_output = standard_output_save; standard_output = standard_output_save;
return str; return str;
} }
curs = strchr(str, '='); curs = strchr(str, '=');
if (!curs || !*curs || (*(curs + 1) == '=')) { if (!curs || !*curs || (*(curs + 1) == '=')) {
curs = str; curs = str;
} }
while (curs && *curs) { while (curs && *curs) {
// search for the first letter of a possible variable // search for the first letter of a possible variable
while (curs && *curs && !isalpha((int)(*curs))) { size_t max = strlen(curs);
if (*curs == '\\') { size_t alpha = find_alpha(curs);
curs++; if (alpha == max) {
while (curs && *curs && isalpha((int)(*curs))) curs++;
}
if (*curs == '\'') {
curs++;
while (curs && *curs && *curs != '\'') curs++;
}
curs++;
}
if (!curs || !*curs) {
break; break;
} }
curs = curs + alpha;
// pull out that variable // pull out that variable
eov = curs;
{ {
size_t i = 0; size_t varlen = 0;
varname = malloc(varnamelen * sizeof(char)); varname = extract_var(curs, &varlen);
while (eov && *eov && eov = curs + varlen;
(isalpha((int)(*eov)) || *eov == '_' || *eov == ':' ||
isdigit((int)(*eov)))) {
if (i == varnamelen - 1) {
varnamelen += 100;
varname = realloc(varname, varnamelen * sizeof(char));
if (varname == NULL) {
perror("flatten: ");
exit(EXIT_FAILURE);
}
}
varname[i++] = *eov;
eov++;
}
if (i == 0) {
break;
}
varname[i] = 0;
} }
olen = strlen(varname);
// if it's a variable, evaluate it
a = getvar_full(varname);
if (!a.err) { // it is a var
Number f;
num_init(f); varvalue = evaluate_var(varname, &a);
if (a.exp) { // it is an expression assert(varvalue);
parseme(a.exp); {
num_set(f, last_answer); size_t nlen = strlen(varvalue);
} else { // it is a value
num_set(f, a.val);
num_free(a.val);
}
// get the number
{
char junk;
// This value must fully reproduce the contents of f (thus, the // now, put it back in the string
-2 in arg 4) // it is a var, and needs parenthesis
varvalue = num_to_str_complex(f, 10, 0, -2, 1, &junk); changedlen = strlen(str) + nlen - strlen(varname) + 1;
} free(varname);
num_free(f);
} else { // not a known var: itza literal (e.g. co
s)
varvalue = (char *)strdup(varname);
} }
nlen = strlen(varvalue);
free(varname);
// now, put it back in the string
// it is a var, and needs parenthesis
changedlen = strlen(str) + nlen - olen + 1;
if (!a.err) { if (!a.err) {
changedlen += 2; // space for parens if it's a variable changedlen += 2; // space for parens if it's a variable
} }
nstr = malloc(changedlen); nstr = malloc(changedlen);
if (!nstr) { // not enough memory if (!nstr) { // not enough memory
perror("flatten: "); perror("flatten: ");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
{ {
char *fromstring = str; char *fromstring = str;
char *tostring = nstr; char *tostring = nstr;
// nstr is the new string, str is the input string // nstr is the new string, str is the input string
tostring = nstr;
while (fromstring != curs) { // copy up to the curs (the begi nning of the var name) while (fromstring != curs) { // copy up to the curs (the begi nning of the var name)
*tostring = *fromstring; *tostring = *fromstring;
++fromstring; ++fromstring;
++tostring; ++tostring;
} }
if (!a.err) { if (!a.err) {
*tostring = '('; *tostring = '(';
++tostring; ++tostring;
} }
fromstring = varvalue; fromstring = varvalue;
skipping to change at line 367 skipping to change at line 434
} }
curs = tostring; curs = tostring;
fromstring = eov; fromstring = eov;
while (fromstring && *fromstring) { while (fromstring && *fromstring) {
*tostring = *fromstring; *tostring = *fromstring;
++fromstring; ++fromstring;
++tostring; ++tostring;
} }
*tostring = 0; *tostring = 0;
free(str); free(str);
str = nstr; str = nstr;
} }
free(varvalue); free(varvalue);
} }
standard_output = standard_output_save; standard_output = standard_output_save;
return str; return str;
} /*}}} */ } /*}}} */
static int recursion(char *str) static int
recursion(char *str)
{ /*{{{ */ { /*{{{ */
List vlist = NULL; List vlist = NULL;
int retval = 0; int retval = 0;
char *righthand; char *righthand;
// do not examine commands // do not examine commands
if (*str == '\\') { if (*str == '\\') {
return 0; return 0;
} }
// do not examine the left side of an assignment // do not examine the left side of an assignment
skipping to change at line 402 skipping to change at line 470
char *varname = (char *)getHeadOfList(vlist); char *varname = (char *)getHeadOfList(vlist);
if (retval == 0) { if (retval == 0) {
retval = find_recursion(varname); retval = find_recursion(varname);
} }
free(varname); free(varname);
} }
return retval; return retval;
} /*}}} */ } /*}}} */
static int find_recursion(char *instring) static int
find_recursion(char *instring)
{ /*{{{ */ { /*{{{ */
List vl = NULL; List vl = NULL;
int retval; int retval;
addToList(&vl, (char *)strdup(instring)); addToList(&vl, (char *)strdup(instring));
retval = find_recursion_core(vl); retval = find_recursion_core(vl);
free(getHeadOfList(vl)); free(getHeadOfList(vl));
return retval; return retval;
} /*}}} */ } /*}}} */
static int find_recursion_core(List oldvars) static int
find_recursion_core(List oldvars)
{ /*{{{ */ { /*{{{ */
List newvars = NULL; List newvars = NULL;
ListIterator oldvarsIterator; ListIterator oldvarsIterator;
int retval = 0; int retval = 0;
struct answer a; struct answer a;
char *newVarname = NULL, *oldVarname = NULL; char *newVarname = NULL;
a = getvar_full((char *)peekAheadInList(oldvars)); a = getvar_full((char *)peekAheadInList(oldvars));
if (a.err) { if (a.err) {
return 0; return 0;
} }
if (!a.exp) { if (!a.exp) {
num_free(a.val); num_free(a.val);
return 0; return 0;
} }
newvars = extract_vars(a.exp); newvars = extract_vars(a.exp);
oldvarsIterator = getListIterator(oldvars); oldvarsIterator = getListIterator(oldvars);
// for each variable in that expression (i.e. each entry in newvars) // for each variable in that expression (i.e. each entry in newvars)
// see if we've seen it before (i.e. it's in oldvars) // see if we've seen it before (i.e. it's in oldvars)
while (listLen(newvars) > 0) { while (listLen(newvars) > 0) {
newVarname = (char *)getHeadOfList(newvars); newVarname = (char *)getHeadOfList(newvars);
char *oldVarname;
while ((oldVarname = while ((oldVarname =
(char *)nextListElement(oldvarsIterator)) != NULL) { (char *)nextListElement(oldvarsIterator)) != NULL) {
if (!strcmp(newVarname, oldVarname)) { if (!strcmp(newVarname, oldVarname)) {
report_error report_error
("%s was found twice in symbol descent. Recursive variables are not allowed.", ("%s was found twice in symbol descent. Recursive variables are not allowed.",
newVarname); newVarname);
// free the rest of the newvars list // free the rest of the newvars list
do { do {
free(newVarname); free(newVarname);
} while ((newVarname = } while ((newVarname =
skipping to change at line 469 skipping to change at line 540
} }
} }
// make sure newvars is empty (so all that memory gets freed) // make sure newvars is empty (so all that memory gets freed)
while ((newVarname = (char *)getHeadOfList(newvars)) != NULL) { while ((newVarname = (char *)getHeadOfList(newvars)) != NULL) {
free(newVarname); free(newVarname);
} }
freeListIterator(oldvarsIterator); freeListIterator(oldvarsIterator);
return retval; return retval;
} /*}}} */ } /*}}} */
void report_error(const char *err_fmt, void
...) report_error(const char *err_fmt,
...)
{ /*{{{ */ { /*{{{ */
extern char *errstring; extern char *errstring;
extern int errloc; extern int errloc;
extern int column; extern int column;
extern int lines; extern int lines;
extern int show_line_numbers; extern int show_line_numbers;
char *tempstring; char *tempstring;
unsigned int len; unsigned int len;
va_list ap; va_list ap;
char *this_error; char *this_error;
va_start(ap, err_fmt); va_start(ap, err_fmt);
this_error = calloc(strlen(err_fmt) + 1000, sizeof(char)); this_error = calloc(strlen(err_fmt) + 1000, sizeof(char));
vsnprintf(this_error, strlen(err_fmt) + 1000, err_fmt, ap); vsnprintf(this_error, strlen(err_fmt) + 1000, err_fmt, ap);
len = strlen(this_error) + 100; len = strlen(this_error) + 100;
va_end(ap); va_end(ap);
/* okay, now this_error has the current error text in it */ /* okay, now this_error has the current error text in it */
if (errstring) { if (errstring) {
len += strlen(errstring); len += strlen(errstring);
} }
tempstring = calloc(len, sizeof(char)); tempstring = calloc(len, sizeof(char));
if (errstring) { if (errstring) {
skipping to change at line 519 skipping to change at line 591
snprintf(tempstring, len, "%s", this_error); snprintf(tempstring, len, "%s", this_error);
} }
} }
errstring = tempstring; errstring = tempstring;
free(this_error); free(this_error);
if (errloc == -1) { if (errloc == -1) {
errloc = column; errloc = column;
} }
} /*}}} */ } /*}}} */
void display_and_clear_errstring() void
{ /*{{{ */ set_prettyanswer(const Number num)
extern int scanerror;
extern char *errstring;
extern int errloc;
if (errstring && errstring[0]) {
if (errloc != -1) {
int i;
fprintf(stderr, " ");
for (i = 0; i < errloc; i++) {
fprintf(stderr, " ");
}
fprintf(stderr, "^\n");
errloc = -1;
}
fprintf(stderr, "%s", errstring);
if (errstring[strlen(errstring) - 1] != '\n') {
fprintf(stderr, "\n");
}
free(errstring);
errstring = NULL;
scanerror = 0;
}
} /*}}} */
void set_prettyanswer(const Number num)
{ /*{{{ */ { /*{{{ */
char *temp; char *temp;
Dprintf("set_prettyanswer\n"); Dprintf("set_prettyanswer\n");
if (pretty_answer) { if (pretty_answer) {
free(pretty_answer); free(pretty_answer);
} }
Dprintf("set_prettyanswer - call print_this_result\n"); Dprintf("set_prettyanswer - call print_this_result\n");
temp = print_this_result(num); temp = print_this_result(num, standard_output, NULL, NULL);
Dprintf("set_prettyanswer: %s\n", temp); Dprintf("set_prettyanswer: %s\n", temp);
if (temp) { if (temp) {
pretty_answer = (char *)strdup(temp); pretty_answer = (char *)strdup(temp);
} else { } else {
pretty_answer = NULL; pretty_answer = NULL;
} }
Dprintf("set_prettyanswer - done\n"); Dprintf("set_prettyanswer - done\n");
} /*}}} */ } /*}}} */
static char *print_this_result_dbl(const double result) static char *
print_this_result_dbl(const double result,
int output,
char *nad,
char **es)
{ /*{{{ */ { /*{{{ */
char format[10]; char format[10];
static char *tmp; static char *tmp;
static char pa_dyn = 1; static char pa_dyn = 1;
extern char *errstring; extern char *errstring;
unsigned int decimal_places = 0; unsigned int decimal_places = 0;
Dprintf("print_this_result_dbl(%f)\n", result); Dprintf("print_this_result_dbl(%f)\n", result);
/* Build the "format" string, that will be used in an snprintf later */ /* Build the "format" string, that will be used in an snprintf later */
switch (conf.output_format) { /*{{{ */ switch (conf.output_format) { /*{{{ */
case DECIMAL_FORMAT: case DECIMAL_FORMAT:
if (pa_dyn) { if (pa_dyn) {
tmp = realloc(pa, sizeof(char) * 310); tmp = realloc(pa, sizeof(char) * 310);
} else { } else {
skipping to change at line 593 skipping to change at line 643
if (!tmp) { if (!tmp) {
free(pa); free(pa);
pa = "Not Enough Memory"; pa = "Not Enough Memory";
pa_dyn = 0; pa_dyn = 0;
return pa; return pa;
} else { } else {
pa = tmp; pa = tmp;
} }
if (conf.precision > -1) { if (conf.precision > -1) {
decimal_places = conf.precision; decimal_places = conf.precision;
switch(conf.engineering) { switch (conf.engineering) {
case never: case never:
snprintf(format, 10, "%%1.%if", conf.precision); snprintf(format, 10, "%%1.%if", conf.precision);
break; break;
case always: case always:
snprintf(format, 10, "%%1.%ie", conf.precision); snprintf(format, 10, "%%1.%ie", conf.precision);
break; break;
case automatic: case automatic:
snprintf(format, 10, "%%1.%ig", conf.precision); snprintf(format, 10, "%%1.%ig", conf.precision);
break; break;
} }
skipping to change at line 775 skipping to change at line 825
case NO_ROUNDING_INDICATION: case NO_ROUNDING_INDICATION:
Dprintf("none\n"); Dprintf("none\n");
not_all_displayed = 0; not_all_displayed = 0;
break; break;
} }
break; break;
} }
case HEXADECIMAL_FORMAT: case HEXADECIMAL_FORMAT:
curs = pa + (conf.print_prefixes ? 2 : 0); curs = pa + (conf.print_prefixes ? 2 : 0);
strswap('.', conf.dec_delimiter, pa); strswap('.', conf.dec_delimiter, pa);
goto hexoct_body;
case OCTAL_FORMAT: case OCTAL_FORMAT:
curs = pa + (conf.print_prefixes ? 1 : 0); curs = pa + (conf.print_prefixes ? 1 : 0);
hexoct_body:
{ {
long int temp = result; long int temp = result;
unsigned int t = 0;
snprintf(pa, 310, format, temp); snprintf(pa, 310, format, temp);
if (conf.rounding_indication == if (conf.rounding_indication ==
SIG_FIG_ROUNDING_INDICATION) { SIG_FIG_ROUNDING_INDICATION) {
if (sig_figs < UINT32_MAX) { if (sig_figs < UINT32_MAX) {
unsigned int t = 0;
while (curs && *curs) { while (curs && *curs) {
++t; ++t;
++curs; ++curs;
} }
not_all_displayed = (t < sig_figs); not_all_displayed = (t < sig_figs);
} else { } else {
not_all_displayed = 0; not_all_displayed = 0;
} }
} else { } else {
not_all_displayed = 0; not_all_displayed = 0;
skipping to change at line 864 skipping to change at line 916
if (conf.print_commas) { if (conf.print_commas) {
char *str = add_commas(pa, conf.output_format); char *str = add_commas(pa, conf.output_format);
if (str) { if (str) {
free(pa); free(pa);
pa = str; pa = str;
} }
} }
if (standard_output) { if (output) {
if (errstring && strlen(errstring)) { show_answer(errstring, not_all_displayed, pa);
display_and_clear_errstring();
}
printf("%s%s\n",
conf.print_equal ? (not_all_displayed ? "~= " : " = ")
: "", pa);
} }
if (nad) { *nad = not_all_displayed; }
if (es) { *es = errstring; }
return pa; return pa;
} /*}}} */ } /*}}} */
char *print_this_result(const Number result) char *
print_this_result(const Number result,
int output,
char *nad,
char **es)
{ /*{{{ */ { /*{{{ */
extern char *errstring; extern char *errstring;
unsigned int base = 0; unsigned int base = 0;
Dprintf("print_this_result (%f) in format %i\n", Dprintf("print_this_result (%f) in format %i\n",
num_get_d(result), conf.output_format); num_get_d(result), conf.output_format);
// output in the proper base and format // output in the proper base and format
switch (conf.output_format) { switch (conf.output_format) {
case HEXADECIMAL_FORMAT: case HEXADECIMAL_FORMAT:
base = 16; base = 16;
skipping to change at line 901 skipping to change at line 954
// then we have to go with the tried and true "double" method // then we have to go with the tried and true "double" method
// ... unless it's an int and you want ints printed whole // ... unless it's an int and you want ints printed whole
// I know that DBL_EPSILON can be calculated like so: // I know that DBL_EPSILON can be calculated like so:
// 2^(mpfr_get_prec(result)-1) HOWEVER, printf magically handles // 2^(mpfr_get_prec(result)-1) HOWEVER, printf magically handles
// numbers like 5.1 that I don't even wanna begin to think about // numbers like 5.1 that I don't even wanna begin to think about
if (conf.precision_guard && (conf.precision < 0)) { if (conf.precision_guard && (conf.precision < 0)) {
Dprintf("precision guard and automatic precision\n"); Dprintf("precision guard and automatic precision\n");
if (!conf.print_ints || !is_int(result)) { if (!conf.print_ints || !is_int(result)) {
// XXX: this doesn't work for *huge* numbers, like 100!+0.1 // XXX: this doesn't work for *huge* numbers, like 100!+0.1
Dprintf("no print_ints or it isn't an int\n"); Dprintf("no print_ints (%i) or it isn't an int (%i)\n", (int )conf.print_ints, (int)is_int(result));
// XXX: what is the following if() for? // XXX: what is the following if() for?
// if (mpfr_get_d(result, GMP_RNDN) != // if (mpfr_get_d(result, GMP_RNDN) !=
// mpfr_get_si(result, GMP_RNDN)) { // mpfr_get_si(result, GMP_RNDN)) {
double res = num_get_d(result); double res = num_get_d(result);
if (fabs(res) < DBL_EPSILON) { if (fabs(res) < DBL_EPSILON) {
res = 0.0; res = 0.0;
} }
return print_this_result_dbl(res); return print_this_result_dbl(res, output, nad, es);
// } // }
} }
} }
base = 10; base = 10;
break; break;
case OCTAL_FORMAT: case OCTAL_FORMAT:
base = 8; base = 8;
break; break;
case BINARY_FORMAT: case BINARY_FORMAT:
base = 2; base = 2;
skipping to change at line 985 skipping to change at line 1038
// add commas // add commas
if (conf.print_commas) { if (conf.print_commas) {
char *str = add_commas(pa, conf.output_format); char *str = add_commas(pa, conf.output_format);
if (str) { if (str) {
free(pa); free(pa);
pa = str; pa = str;
} }
} }
if (standard_output) { if (output) {
if (errstring && strlen(errstring)) { show_answer(errstring, not_all_displayed, pa);
display_and_clear_errstring();
}
printf("%s%s\n",
conf.print_equal ? (not_all_displayed ? "~= " : " = ")
: "", pa);
} }
if (nad) { *nad = not_all_displayed; }
if (es) { *es = errstring; }
return pa; return pa;
} /*}}} */ } /*}}} */
void simple_exp(Number output, void
const Number first, simple_exp(Number output,
const enum operations op, const Number first,
const Number second) const enum operations op,
const Number second)
{ /*{{{ */ { /*{{{ */
if (compute) { if (compute) {
Number temp; Number temp;
num_init(temp); num_init(temp);
Dprintf("simple_exp: %f %i %f\n", num_get_d(first), op, Dprintf("simple_exp: %f %i %f\n", num_get_d(first), op,
num_get_d(second)); num_get_d(second));
switch (op) { switch (op) {
default: default:
skipping to change at line 1108 skipping to change at line 1159
} }
Dprintf("returns: %f\n", num_get_d(output)); Dprintf("returns: %f\n", num_get_d(output));
num_free(temp); num_free(temp);
return; return;
} else { } else {
num_set_ui(output, 0); num_set_ui(output, 0);
return; return;
} }
} /*}}} */ } /*}}} */
void uber_function(Number output, void
const enum functions func, uber_function(Number output,
Number input) const enum functions func,
Number input)
{ /*{{{ */ { /*{{{ */
if (compute) { if (compute) {
Number temp; Number temp;
num_init(temp); num_init(temp);
if (!conf.use_radians) { if (!conf.use_radians) {
switch (func) { switch (func) {
case wsin: case wsin:
case wcos: case wcos:
case wtan: case wtan:
skipping to change at line 1327 skipping to change at line 1379
break; break;
} }
num_free(temp); num_free(temp);
return; return;
} else { } else {
num_set_ui(output, 0); num_set_ui(output, 0);
return; return;
} }
} /*}}} */ } /*}}} */
char *output_string(const unsigned int o) char *
output_string(const unsigned int o)
{ /*{{{ */ { /*{{{ */
switch (o) { switch (o) {
case HEXADECIMAL_FORMAT: case HEXADECIMAL_FORMAT:
return "hexadecimal format (0xf)"; return "hexadecimal format (0xf)";
case OCTAL_FORMAT: case OCTAL_FORMAT:
return "octal format (08) "; return "octal format (08) ";
case BINARY_FORMAT: case BINARY_FORMAT:
return "binary format (0b1) "; return "binary format (0b1) ";
 End of changes. 56 change blocks. 
148 lines changed or deleted 200 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS