diff --git a/src/common/cell.c b/src/common/cell.c index a0b18a3..5599c35 100644 --- a/src/common/cell.c +++ b/src/common/cell.c @@ -249,9 +249,9 @@ static int print_string(char* dest, size_t space, /*}}}*/ /* printtok -- print a single token, passed by address, although not changed */ /*{{{*/ -size_t printtok(char* dest, size_t size, size_t field_width, - StringFormat sf, FloatFormat ff, - int digits, ErrorFormat ef, const Token *tok) +size_t ptokatprec(char* dest, size_t size, size_t field_width, StringFormat sf, + FloatFormat ff, int digits, ErrorFormat ef, const Token *tok, + FunctionPrecedence atprec) { if (debug_level > 2) { printf("..Entering printtok; bufsize %d, field_width %d, qs %d, ff %s," @@ -381,17 +381,76 @@ size_t printtok(char* dest, size_t size, size_t field_width, /* FUNCALL */ /*{{{*/ case FUNCALL: { - cur += print_fident(dest+cur, size-cur-1, tok->u.funcall.fident); - if (tok->u.funcall.argc >= 0 && cur + 2 < size) /* -1 args is bare func */ + FunctionIdentifier fid = tok->u.funcall.fident; + if (tok->u.funcall.argc <= 0) { - dest[cur++] = '\('; + cur += print_fident(dest+cur, size-cur-1, fid); + if (tok->u.funcall.argc == 0) + { + if (cur < size - 2) { dest[cur++] = '('; dest[cur++] = ')'; } + else cur += 2; + } + break; + } + FunctionPrecedence fp = tfunc[fid].precedence; + switch (fp) + { + case PREFIX_FUNC: { + cur += print_fident(dest+cur, size-cur-1, fid); + if (cur < size) dest[cur++] = '('; for (size_t ai = 0; ai < tok->u.funcall.argc && cur < size-1; ++ai) { if (ai > 0 && cur < size) dest[cur++] = ','; - cur += printtok(dest+cur, size-cur-1, field_width-cur, sf, ff, - digits, ef, tok->u.funcall.argv + ai); + /* The commas eliminate the need for precedence worries in arguments*/ + cur += ptokatprec(dest+cur, size-cur-1, field_width-cur, sf, ff, + digits, ef, tok->u.funcall.argv + ai, + NO_PRECEDENCE); } if (cur < size) dest[cur++] = ')'; + break; + } + case PREFIX_NEG: { + assert(tok->u.funcall.argc == 1); + assert(tfunc[fid].display_symbol != NULL); + if (fp < atprec && cur < size) dest[cur++] = '('; + if (cur < size) { + strncpy(dest+cur, tfunc[fid].display_symbol, size-cur-1); + cur += strlen(tfunc[fid].display_symbol); + } + cur += ptokatprec(dest+cur, size-cur-1, field_width-cur, sf, ff, + digits, ef, tok->u.funcall.argv, fp); + if (fp < atprec && cur < size) dest[cur++] = ')'; + break; + } + default: /* infix argument */ + assert(tok->u.funcall.argc > 1); + if (fp < atprec && cur < size) dest[cur++] = '('; + for (size_t ai = 0; ai < tok->u.funcall.argc && cur < size-1; ++ ai) + { + bool parenarg = false; + if (ai > 0) { + if (fp < INFIX_MUL && cur < size) dest[cur++] = ' '; + const char *use = tfunc[fid].display_symbol; + if (use == NULL) use = tfunc[fid].name; + strncpy(dest+cur, use, size-cur-1); + cur += strlen(use); + if (fp < INFIX_MUL && cur < size) dest[cur++] = ' '; + } else if (fp > PREFIX_NEG) { + char powbuf[4096]; + size_t arglen = ptokatprec(powbuf, sizeof(powbuf), 0, sf, ff, + digits, ef, tok->u.funcall.argv, fp); + assert(arglen < sizeof(powbuf)-1); + if (powbuf[0] == '-') { + parenarg = true; + if (cur < size) dest[cur++] = '('; + } + } + cur += ptokatprec(dest+cur, size-cur-1, field_width-cur, sf, ff, + digits, ef, tok->u.funcall.argv + ai, fp); + if (parenarg && cur < size) dest[cur++] = ')'; + } + if (fp < atprec && cur < size) dest[cur++] = ')'; + break; } break; } @@ -439,6 +498,16 @@ size_t printtok(char* dest, size_t size, size_t field_width, } /*}}}*/ +/* printtok -- print a single token, passed by address, although not changed */ /*{{{*/ +size_t printtok(char* dest, size_t size, size_t field_width, + StringFormat sf, FloatFormat ff, + int digits, ErrorFormat ef, const Token *tok) +{ + return ptokatprec(dest, size, field_width, sf, ff, digits, ef, tok, + NO_PRECEDENCE); +} +/*}}}*/ + /* print -- print token sequence */ /*{{{*/ void print(char *s, size_t size, size_t chars, StringFormat sf, FloatFormat ff, int digits, Token **n) diff --git a/src/common/func.c b/src/common/func.c index 9a135c4..9fff2dc 100644 --- a/src/common/func.c +++ b/src/common/func.c @@ -390,7 +390,7 @@ static Token at_func(int argc, const Token argv[], LocConvention lcon) strcat(result.u.err, location.u.err); /* don't free the location if it is the same as an argument, because those get freed later: */ - for (size_t i = 0; i < argc; ++i) + for (int i = 0; i < argc; ++i) if (argv[i].type == EEK & argv[i].u.err == location.u.err) return result; tfree(&location); return result; diff --git a/src/common/func.h b/src/common/func.h index a34958c..5fe5cf1 100644 --- a/src/common/func.h +++ b/src/common/func.h @@ -36,8 +36,8 @@ typedef struct Token_struc Token; typedef enum /* In increasing order of precedence */ { - INFIX_CONC, INFIX_REL, INFIX_PLUS, INFIX_MUL, PREFIX_NEG, - INFIX_POW, PREFIX_FUNC + NO_PRECEDENCE, INFIX_CONC, INFIX_REL, INFIX_PLUS, INFIX_MUL, + PREFIX_NEG, INFIX_POW, PREFIX_FUNC } FunctionPrecedence; typedef enum { FUNCT, MACRO } EvaluationStrategy;