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.11 2017/12/02 04:32:42 tg Exp $");
25 volatile sig_atomic_t merrf;
26 const unsigned char *merrt;
29 static char math_res[JOE_MSGBUFSIZE];
30 static char *math_exp;
32 static RETSIGTYPE fperr(int unused)
36 REINSTALL_SIGHANDLER(SIGFPE, fperr);
46 static struct var *get(unsigned char *str)
50 for (v = vars; v; v = v->next) {
51 if (!strcmp(v->name, str)) {
55 v = (struct var *) joe_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') {
92 sscanf((char *)ptr, "%li", &xi);
95 while ((*ptr >= '0' && *ptr <= '9') || ((*ptr | 0x20) >= 'a' && (*ptr | 0x20) <= 'f'))
97 } else if ((*ptr >= '0' && *ptr <= '9') || *ptr == '.') {
98 x = strtod(ptr, &ptr);
99 } else if (*ptr == '(') {
106 merrt = US "Missing )";
108 } else if (*ptr == '-') {
110 x = -expr(10, &dumb);
113 while (*ptr == ' ' || *ptr == '\t')
115 if (*ptr == '*' && 5 > prec) {
119 } else if (*ptr == '/' && 5 > prec) {
123 } else if (*ptr == '+' && 4 > prec) {
127 } else if (*ptr == '-' && 4 > prec) {
131 } else if (*ptr == '=' && 2 >= prec) {
139 merrt = US "Left side of = is not an l-value";
147 #if defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG > 0)
148 typedef long long joe_imaxt;
149 #define JOE_IMAXT "ll"
151 typedef long joe_imaxt;
152 #define JOE_IMAXT "l"
155 double calc(BW *bw, unsigned char *s)
159 BW *tbw = bw->parent->main->object;
164 math_exp = strdup((void *)s);
167 v->val = tbw->top->line + 1;
170 v->val = tbw->b->eof->line + 1;
173 v->val = tbw->cursor->line + 1;
176 v->val = tbw->cursor->col + 1;
179 v->val = tbw->cursor->byte + 1;
181 v = get(US "height");
190 result = expr(0, &dumb);
192 while (*ptr == ' ' || *ptr == '\t') {
197 while (*ptr == ' ' || *ptr == '\t') {
203 } else if (*ptr && !merrf) {
205 merrt = US "Extra junk after end of expr";
211 merrt = US "Float point exception";
212 joe_snprintf_1(math_res, JOE_MSGBUFSIZE,
213 "math_error{%s}", merrt);
215 joe_imaxt ires = (joe_imaxt)result;
217 if ((double)ires == result) {
218 /* representable as integer value */
219 joe_snprintf_1(math_res, JOE_MSGBUFSIZE,
220 "%" JOE_IMAXT "d", ires);
222 /* use float with large precision */
223 joe_snprintf_1(math_res, JOE_MSGBUFSIZE,
231 /* Main user interface */
232 static int domath(BW *bw, unsigned char *s, void *object, int *notify)
240 msgnw(bw->parent, merrt);
244 memcpy(msgbuf, math_res, JOE_MSGBUFSIZE);
245 if (bw->parent->watom->what != TYPETW) {
246 binsm(bw->cursor, sz(msgbuf));
247 pfwrd(bw->cursor, strlen((char *)msgbuf));
248 bw->cursor->xcol = piscol(bw->cursor);
250 msgnw(bw->parent, msgbuf);
259 joe_set_signal(SIGFPE, fperr);
260 if (wmkpw(bw->parent, US "=", &mathhist, domath, US "math", NULL, NULL, NULL, NULL, locale_map)) {
270 binss(bw->cursor, (void *)math_exp);
277 binss(bw->cursor, (void *)math_res);
282 calcl(BW *bw, unsigned char *s)
287 rv = ustol(s, &cp, USTOL_TRIM | USTOL_EOS);
290 merrt = US "Invalid or out-of-range number";
299 msgnw(bw->parent, US "Sorry, compiled without Math");