4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/umath.c,v 1.24 2017/12/08 02:28:08 tg Exp $");
24 volatile sig_atomic_t merrf;
25 const unsigned char *merrt;
28 static char math_res[JOE_MSGBUFSIZE];
29 static char *math_exp;
31 static double calc(BW *bw, unsigned char *s);
33 static RETSIGTYPE fperr(int unused)
37 REINSTALL_SIGHANDLER(SIGFPE, fperr);
47 static struct var *get(unsigned char *str)
51 for (v = vars; v; v = v->next) {
52 if (!strcmp(v->name, str)) {
56 v = malloc(sizeof(struct var));
60 v->name = (unsigned char *)strdup((char *)str);
67 static double expr(int prec, struct var **rtv)
72 while (*ptr == ' ' || *ptr == '\t') {
75 if ((*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z')
77 unsigned char *s = ptr, c;
79 while ((*ptr >= 'a' && *ptr <= 'z')
80 || (*ptr >= 'A' && *ptr <= 'Z')
81 || *ptr == '_' || (*ptr >= '0' && *ptr <= '9')) {
89 } else if (ptr[0] == '0' && (ptr[1] | 0x20) == 'x') {
93 xi = ustol(ptr, &dp, USTOL_AUTO);
96 } else if ((*ptr >= '0' && *ptr <= '9') || *ptr == '.') {
99 x = strtod(ptr, &eptr);
100 ptr = (unsigned char *)eptr;
101 } else if (*ptr == '(') {
108 merrt = US "Missing )";
110 } else if (*ptr == '-') {
112 x = -expr(10, &dumb);
115 while (*ptr == ' ' || *ptr == '\t')
117 if (*ptr == '*' && 5 > prec) {
121 } else if (*ptr == '/' && 5 > prec) {
125 } else if (*ptr == '+' && 4 > prec) {
129 } else if (*ptr == '-' && 4 > prec) {
133 } else if (*ptr == '=' && 2 >= prec) {
141 merrt = US "Left side of = is not an l-value";
149 #if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG > 0)
150 typedef long long joe_imaxt;
151 #define JOE_IMAXT "ll"
153 typedef long joe_imaxt;
154 #define JOE_IMAXT "l"
158 calc(BW *bw, unsigned char *s)
162 BW *tbw = bw->parent->main->object.bw;
167 math_exp = strdup((void *)s);
170 v->val = tbw->top->line + 1;
173 v->val = tbw->b->eof->line + 1;
176 v->val = tbw->cursor->line + 1;
179 v->val = tbw->cursor->col + 1;
182 v->val = tbw->cursor->byte + 1;
184 v = get(US "height");
193 result = expr(0, &dumb);
195 while (*ptr == ' ' || *ptr == '\t') {
200 while (*ptr == ' ' || *ptr == '\t') {
206 } else if (*ptr && !merrf) {
208 merrt = US "Extra junk after end of expr";
214 merrt = US "Float point exception";
215 joe_snprintf_1(math_res, JOE_MSGBUFSIZE,
216 "math_error{%s}", merrt);
218 joe_imaxt ires = (joe_imaxt)result;
220 if ((double)ires == result) {
221 /* representable as integer value */
222 joe_snprintf_1(math_res, JOE_MSGBUFSIZE,
223 "%" JOE_IMAXT "d", ires);
225 /* use float with large precision */
226 joe_snprintf_1(math_res, JOE_MSGBUFSIZE,
234 /* Main user interface */
235 static int domath(BW *bw, unsigned char *s, void *object, int *notify)
244 msgnw(bw->parent, merrt);
247 memcpy(msgbuf, math_res, JOE_MSGBUFSIZE);
248 if (bw->parent->watom->what != TYPETW) {
249 binsm(bw->cursor, sz(msgbuf));
250 pfwrd(bw->cursor, strlen((char *)msgbuf));
251 bw->cursor->xcol = piscol(bw->cursor);
253 msgnw(bw->parent, msgbuf);
262 joe_set_signal(SIGFPE, fperr);
263 if (wmkpw(bw->parent, UC "=", &mathhist, domath, UC "Math", NULL, NULL, NULL, NULL, locale_map)) {
273 binss(bw->cursor, (void *)math_exp);
280 binss(bw->cursor, (void *)math_res);
285 calcl(BW *bw, unsigned char *s)
294 calcl(BW *bw, unsigned char *s)
299 rv = ustol(s, &cp, USTOL_TRIM | USTOL_EOS);
302 merrt = US "Invalid or out-of-range number";
311 msgnw(bw->parent, UC "Sorry, compiled without Math");