static int charConvert(ej_t* ep, int base, int maxDig) { int i, c, lval, convChar; lval = 0; for (i = 0; i < maxDig; i++) { if ((c = inputGetc(ep)) < 0) { break; } /* * Initialize to out of range value */ convChar = base; if (gisdigit(c)) { convChar = c - '0'; } else if (c >= 'a' && c <= 'f') { convChar = c - 'a' + 10; } else if (c >= 'A' && c <= 'F') { convChar = c - 'A' + 10; } /* * if unexpected character then return it to buffer. */ if (convChar >= base) { inputPutback(ep, c); break; } lval = (lval * base) + convChar; } return lval; }
static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs) { char_t buf[16]; int l, r, lval; a_assert(lhs); a_assert(rhs); a_assert(rel > 0); lval = 0; if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) { l = gatoi(lhs); r = gatoi(rhs); switch (rel) { case COND_AND: lval = l && r; break; case COND_OR: lval = l || r; break; default: ejError(ep, T("Bad operator %d"), rel); return -1; } } else { if (!gisdigit((int)*lhs)) { ejError(ep, T("Conditional must be numeric"), lhs); } else { ejError(ep, T("Conditional must be numeric"), rhs); } } stritoa(lval, buf, sizeof(buf)); setString(B_L, &ep->result, buf); return 0; }
//---------------------------------------------------------------------------- // convert decimal/hexadecimal number to tUint32 //---------------------------------------------------------------------------- tUint32 xstrToUint32(tCChar* pIn) { register tUint32 dwOut = 0; // handle hexadecimal format 0x..... if ((*pIn == '0') && ((*(pIn + 1) == 'x') || (*(pIn + 1) == 'X'))) { for (pIn += 2; gisxdigit(*pIn); pIn++) dwOut = (dwOut * 16) + ((*pIn > '9') ? ((*pIn & 0x07) + 9) : (*pIn - '0')); } // if else { for ( ; gisdigit(*pIn); pIn++) dwOut = (dwOut * 10) + (*pIn - '0'); } // else return dwOut; } // xstrToUint32
tUint32 xstrToUint32(tUint32& dwOut, tCChar* pIn) { dwOut = 0; // handle hexadecimal format 0x..... if ((*pIn == '0') && ((*(pIn + 1) == 'x') || (*(pIn + 1) == 'X'))) { for (pIn += 2; gisxdigit(*pIn); pIn++) dwOut = (dwOut * 16) + ((*pIn > '9') ? ((*pIn & 0x07) + 9) : (*pIn - '0')); } // if else { for ( ; gisdigit(*pIn); pIn++) dwOut = (dwOut * 10) + (*pIn - '0'); } // else // for (dwOut = 0; gisdigit(*pIn); pIn++) // dwOut = (dwOut * 10) + (*pIn - '0'); return (*pIn) ? XERROR_SYNTAX : XERROR_SUCCESS; } // xstrToUint32
static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs) { char_t *cp, buf[16]; int numeric, l, r, lval; a_assert(lhs); a_assert(rhs); a_assert(rel > 0); /* * All of the characters in the lhs and rhs must be numeric */ numeric = 1; for (cp = lhs; *cp; cp++) { if (!gisdigit((int)*cp)) { numeric = 0; break; } } if (numeric) { for (cp = rhs; *cp; cp++) { if (!gisdigit((int)*cp)) { numeric = 0; break; } } } if (numeric) { l = gatoi(lhs); r = gatoi(rhs); switch (rel) { case EXPR_PLUS: lval = l + r; break; case EXPR_INC: lval = l + 1; break; case EXPR_MINUS: lval = l - r; break; case EXPR_DEC: lval = l - 1; break; case EXPR_MUL: lval = l * r; break; case EXPR_DIV: if (r != 0) { lval = l / r; } else { lval = 0; } break; case EXPR_MOD: if (r != 0) { lval = l % r; } else { lval = 0; } break; case EXPR_LSHIFT: lval = l << r; break; case EXPR_RSHIFT: lval = l >> r; break; case EXPR_EQ: lval = l == r; break; case EXPR_NOTEQ: lval = l != r; break; case EXPR_LESS: lval = (l < r) ? 1 : 0; break; case EXPR_LESSEQ: lval = (l <= r) ? 1 : 0; break; case EXPR_GREATER: lval = (l > r) ? 1 : 0; break; case EXPR_GREATEREQ: lval = (l >= r) ? 1 : 0; break; case EXPR_BOOL_COMP: lval = (r == 0) ? 1 : 0; break; default: ejError(ep, T("Bad operator %d"), rel); return -1; } } else { switch (rel) {
static int getLexicalToken(ej_t* ep, int state) { ringq_t *inq, *tokq; ejinput_t* ip; int done, tid, c, quote, style; a_assert(ep); ip = ep->input; a_assert(ip); inq = &ip->script; tokq = &ip->tokbuf; ep->tid = -1; tid = -1; ep->token = T(""); ringqFlush(tokq); if (ip->putBackTokenId > 0) { ringqPutStr(tokq, ip->putBackToken); tid = ip->putBackTokenId; ip->putBackTokenId = 0; ep->token = (char_t*) tokq->servp; return tid; } if ((c = inputGetc(ep)) < 0) { return TOK_EOF; } for (done = 0; !done; ) { switch (c) { case -1: return TOK_EOF; case ' ': case '\t': case '\r': do { if ((c = inputGetc(ep)) < 0) break; } while (c == ' ' || c == '\t' || c == '\r'); break; case '\n': return TOK_NEWLINE; case '(': tokenAddChar(ep, c); return TOK_LPAREN; case ')': tokenAddChar(ep, c); return TOK_RPAREN; case '{': tokenAddChar(ep, c); return TOK_LBRACE; case '}': tokenAddChar(ep, c); return TOK_RBRACE; case '+': if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c != '+' ) { inputPutback(ep, c); tokenAddChar(ep, EXPR_PLUS); return TOK_EXPR; } tokenAddChar(ep, EXPR_INC); return TOK_INC_DEC; case '-': if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c != '-' ) { inputPutback(ep, c); tokenAddChar(ep, EXPR_MINUS); return TOK_EXPR; } tokenAddChar(ep, EXPR_DEC); return TOK_INC_DEC; case '*': tokenAddChar(ep, EXPR_MUL); return TOK_EXPR; case '%': tokenAddChar(ep, EXPR_MOD); return TOK_EXPR; case '/': /* * Handle the division operator and comments */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c != '*' && c != '/') { inputPutback(ep, c); tokenAddChar(ep, EXPR_DIV); return TOK_EXPR; } style = c; /* * Eat comments. Both C and C++ comment styles are supported. */ while (1) { if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '\n' && style == '/') { break; } else if (c == '*') { c = inputGetc(ep); if (style == '/') { if (c == '\n') { break; } } else { if (c == '/') { break; } } } } /* * Continue looking for a token, so get the next character */ if ((c = inputGetc(ep)) < 0) { return TOK_EOF; } break; case '<': /* < and <= */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '<') { tokenAddChar(ep, EXPR_LSHIFT); return TOK_EXPR; } else if (c == '=') { tokenAddChar(ep, EXPR_LESSEQ); return TOK_EXPR; } tokenAddChar(ep, EXPR_LESS); inputPutback(ep, c); return TOK_EXPR; case '>': /* > and >= */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '>') { tokenAddChar(ep, EXPR_RSHIFT); return TOK_EXPR; } else if (c == '=') { tokenAddChar(ep, EXPR_GREATEREQ); return TOK_EXPR; } tokenAddChar(ep, EXPR_GREATER); inputPutback(ep, c); return TOK_EXPR; case '=': /* "==" */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '=') { tokenAddChar(ep, EXPR_EQ); return TOK_EXPR; } inputPutback(ep, c); return TOK_ASSIGNMENT; case '!': /* "!=" or "!"*/ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '=') { tokenAddChar(ep, EXPR_NOTEQ); return TOK_EXPR; } inputPutback(ep, c); tokenAddChar(ep, EXPR_BOOL_COMP); return TOK_EXPR; case ';': tokenAddChar(ep, c); return TOK_SEMI; case ',': tokenAddChar(ep, c); return TOK_COMMA; case '|': /* "||" */ if ((c = inputGetc(ep)) < 0 || c != '|') { ejError(ep, T("Syntax Error")); return TOK_ERR; } tokenAddChar(ep, COND_OR); return TOK_LOGICAL; case '&': /* "&&" */ if ((c = inputGetc(ep)) < 0 || c != '&') { ejError(ep, T("Syntax Error")); return TOK_ERR; } tokenAddChar(ep, COND_AND); return TOK_LOGICAL; case '\"': /* String quote */ case '\'': quote = c; if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } while (c != quote) { /* * check for escape sequence characters */ if (c == '\\') { c = inputGetc(ep); if (gisdigit(c)) { /* * octal support, \101 maps to 65 = 'A'. put first char * back so converter will work properly. */ inputPutback(ep, c); c = charConvert(ep, OCTAL, 3); } else { switch (c) { case 'n': c = '\n'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'x': /* * hex support, \x41 maps to 65 = 'A' */ c = charConvert(ep, HEX, 2); break; case 'u': /* * unicode support, \x0401 maps to 65 = 'A' */ c = charConvert(ep, HEX, 2); c = c*16 + charConvert(ep, HEX, 2); break; case '\'': case '\"': case '\\': break; default: ejError(ep, T("Invalid Escape Sequence")); return TOK_ERR; } } if (tokenAddChar(ep, c) < 0) { return TOK_ERR; } } else { if (tokenAddChar(ep, c) < 0) { return TOK_ERR; } } if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Unmatched Quote")); return TOK_ERR; } } return TOK_LITERAL; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { if (tokenAddChar(ep, c) < 0) { return TOK_ERR; } if ((c = inputGetc(ep)) < 0) break; } while (gisdigit(c)); inputPutback(ep, c); return TOK_LITERAL; default: /* * Identifiers or a function names */ while (1) { if (c == '\\') { /* * just ignore any \ characters. */ } else if (tokenAddChar(ep, c) < 0) { break; } if ((c = inputGetc(ep)) < 0) { break; } if (!gisalnum(c) && c != '$' && c != '_' && c != '\\') { break; } } if (! gisalpha(*tokq->servp) && *tokq->servp != '$' && *tokq->servp != '_') { ejError(ep, T("Invalid identifier %s"), tokq->servp); return TOK_ERR; } /* * Check for reserved words (only "if", "else", "var", "for" * and "return" at the moment) */ if (state == STATE_STMT) { if (gstrcmp(ep->token, T("if")) == 0) { return TOK_IF; } else if (gstrcmp(ep->token, T("else")) == 0) { return TOK_ELSE; } else if (gstrcmp(ep->token, T("var")) == 0) { return TOK_VAR; } else if (gstrcmp(ep->token, T("for")) == 0) { return TOK_FOR; } else if (gstrcmp(ep->token, T("return")) == 0) { if ((c == ';') || (c == '(')) { inputPutback(ep, c); } return TOK_RETURN; } } /* * Skip white space after token to find out whether this is * a function or not. */ while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { if ((c = inputGetc(ep)) < 0) break; } tid = (c == '(') ? TOK_FUNCTION : TOK_ID; done++; } } /* * Putback the last extra character for next time */ inputPutback(ep, c); return tid; }