From bc6424cdf290d1767fa4cb92da560bafd563c584 Mon Sep 17 00:00:00 2001 From: ketmar Date: Thu, 25 Jun 2020 05:45:04 +0000 Subject: [PATCH] fixed macro argument expander (it will not drop expression tail anymore) FossilOrigin-Name: 7d8537dd373a41b5ac3b0c54824a2bf5bb7eafd14ebd49b64a9fa2d2b5e08415 --- src/urasm.c | 78 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/src/urasm.c b/src/urasm.c index 0302aed..04ee039 100644 --- a/src/urasm.c +++ b/src/urasm.c @@ -2848,12 +2848,12 @@ static int piIFX (void) { return piIFAll(1); } // first term char will not be skipped // must return pointer to the first char after expression end static const char *getValueCB (urasm_exprval_t *res, const char *expr, uint16_t addr, int donteval, int *defined, int *error) { - char name[257], *p = name; - // + char name[257]; + char *p = name; + if (curmacro == NULL) fatal("'=' outside of macro"); if (*expr++ != '=') fatal("'=' expected!"); - //fprintf(stderr, "GV: [%s]\n", expr); - // + expr = strSkipSpaces(expr); while (*expr) { if (isAlphaDigit(*expr) || *expr == '_') { @@ -2864,14 +2864,14 @@ static const char *getValueCB (urasm_exprval_t *res, const char *expr, uint16_t break; } *p = 0; + expr = strSkipSpaces(expr); for (int f = 0; f < curmacro->mac->argc; ++f) { if (strcasecmp(name, curmacro->mac->argnames[f]) == 0) { if (*expr == '[') { urasm_exprval_t v; - int l = strlen(curmacro->argvals[f]); - // - ++expr; + int l = (int)strlen(curmacro->argvals[f]); + ++expr; // skip "[" urasm_exprval_init(&v); expr = urasm_expr_ex(&v, expr, addr, &donteval, defined, error); if (*error) return expr; @@ -2886,24 +2886,27 @@ static const char *getValueCB (urasm_exprval_t *res, const char *expr, uint16_t return expr; } else { urasm_expr_ex(res, curmacro->argvals[f], addr, &donteval, defined, error); - //fprintf(stderr, "GV: [%s] [%s] [%d]\n", name, curmacro->argvals[f], res->val); return expr; } } } + fatal("unknown macro variable: '%s'", name); } //!0: error; oprlen is opr size (w/o ending 0), it's 255 for now +// opr starts with '=' (invariant) static int expandCB (char *opr, int oprlen) { char name[257], *p = name, *op = opr; - // + if (curmacro == NULL) fatal("'=' outside of macro"); - if (*op++ != '=') fatal("'=' expected!"); + if (*op++ != '=') fatal("'=' expected!"); // just in case //fprintf(stderr, "expand: [%s]\n", opr); - //fatal("!!!"); - op = strSkipSpaces(op); + + if (!isAlpha(op[0])) return 0; // nothing to do + + // copy argument name while (*op) { if (isAlphaDigit(*op) || *op == '_') { if (p-name > 250) fatal("id too long"); @@ -2913,35 +2916,38 @@ static int expandCB (char *opr, int oprlen) { break; } *p = 0; + + // expand argument? we only need to expand `=arg[n]` op = strSkipSpaces(op); + if (op[0] != '[') return 0; + for (int f = 0; f < curmacro->mac->argc; ++f) { if (strcasecmp(name, curmacro->mac->argnames[f]) == 0) { - if (*op == '[') { - urasm_exprval_t v; - int l = strlen(curmacro->argvals[f]), error = 0, defined = 1, donteval = 0; - // - ++op; - urasm_exprval_init(&v); - op = (char *)urasm_expr_ex(&v, op, pc, &donteval, &defined, &error); - if (error) return -1; - if (op == NULL || *op != ']' || v.str != NULL) return -1; - op = strSkipSpaces(op+1); - if (*op) return -1; - if (v.val < 0) v.val += l; - if (v.val < 0 || v.val >= l) { - strcpy(opr, "?"); - } else { - opr[0] = curmacro->argvals[f][v.val]; - opr[1] = 0; - } - return 0; - } - // - strncpy(opr, curmacro->argvals[f], oprlen); - opr[oprlen-1] = 0; - return (*op ? -1 : 0); + if (*op != '[') abort(); // assertion, just in case + // replace argument with character + // used for `=regpair[0]` + urasm_exprval_t v; + int error = 0, defined = 1, donteval = 0; + ++op; // skip '[' + urasm_exprval_init(&v); + op = (char *)urasm_expr_ex(&v, op, pc, &donteval, &defined, &error); + if (error) return -1; + // result should be a number + if (op == NULL || *op != ']' || v.str != NULL) return -1; + ++op; // skip ']' + // it is guaranteed to have more than one char in opr + // so we can simply put char from argument value, and remove other expression chars + const int l = (int)strlen(curmacro->argvals[f]); + if (v.val < 0) v.val += l; // negative: indexing from the end + if (v.val < 0 || v.val >= l) fatal("index %d is out of bounds for macro argument '%s'", v.val, curmacro->mac->argnames[f]); + // copy char + opr[0] = curmacro->argvals[f][v.val]; + // remove other chars + memmove(opr+1, op, strlen(op)+1); + return 0; } } + fatal("unknown macro variable: '%s'", name); } -- 2.11.4.GIT