/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include #include #include #include #include #include "_compute.h" #include "_compparse.h" /* If this char is 0, return 0, else space on */ #define input() (*_dxfccsptr++) #define unput() (_dxfccsptr--) #define MAXTOKEN 200 static char *_dxfccsbuf; static char *_dxfccsptr; /* * these are key words used for operators (NOT functions!) */ static struct keytab { char *name; int value; } keytab [] = { { "cross", T_CROSS }, { "dot", T_DOT }, { "mod", T_MOD } }; _dxfccinput(char *buffer) { #if defined(_CCDEBUG) extern int _dxfccdebug; #endif _dxfccsbuf = buffer; _dxfccsptr = _dxfccsbuf; #if defined(_CCDEBUG) _dxfccdebug = 1; #endif } int _dxfcclexerror() { return (_dxfccsptr - _dxfccsbuf); } /* * analyze the input and return the next lexical token */ static int lastToken = T_EOF; #define LEX_RETURN(t) return (lastToken = (t)); int _dxfcclex() { int c; char _dxfcctext[MAXTOKEN]; int _dxfccleng; int i; double d; int isDouble; for (;;) { _dxfccleng = 0; c = input(); switch (c) { case 0: LEX_RETURN(T_EOF); case '(': LEX_RETURN(T_LPAR); case ')': LEX_RETURN(T_RPAR); case '{': LEX_RETURN(T_LBRA); case '}': LEX_RETURN(T_RBRA); case '[': LEX_RETURN(T_LSQB); case ']': LEX_RETURN(T_RSQB); case ',': LEX_RETURN(T_COMMA); case '|': c = input(); if (c == '|') LEX_RETURN(T_LOR); unput(); LEX_RETURN('|'); case '&': c = input(); if (c == '&') LEX_RETURN(T_LAND); unput(); LEX_RETURN('&'); case '!': c = input(); if (c == '=') LEX_RETURN(T_NE); unput(); LEX_RETURN(T_LNOT); case '<': c = input(); if (c == '=') LEX_RETURN(T_LE); unput(); LEX_RETURN(T_LT); case '>': c = input(); if (c == '=') LEX_RETURN(T_GE); unput(); LEX_RETURN(T_GT); case '=': c = input(); if (c == '=') LEX_RETURN(T_EQ); unput(); LEX_RETURN(T_ASSIGN); case '?': LEX_RETURN(T_QUEST); case ':': LEX_RETURN(T_COLON); case ';': LEX_RETURN(T_SEMI); case '+': LEX_RETURN(T_PLUS); case '-': LEX_RETURN(T_MINUS); case '*': c = input(); if (c == '*') LEX_RETURN(T_EXP); unput(); LEX_RETURN(T_TIMES); case '/': LEX_RETURN(T_DIV); case '^': LEX_RETURN(T_EXP); case '%': LEX_RETURN(T_MOD); case '$': /* input variables */ c = input(); while (isdigit(c)) { _dxfcctext[_dxfccleng++] = c; c = input(); } _dxfcctext[_dxfccleng] = '\0'; _dxfcclval.i = atoi(_dxfcctext); unput(); if (_dxfcclval.i >= MAX_INPUTS) { DXSetError(ERROR_BAD_PARAMETER, "#12070", _dxfcclval.i, MAX_INPUTS); LEX_RETURN(ERROR); } else { LEX_RETURN(T_INPUT); } case ' ': /* white space */ case '\t': break; case '\'': { int i=0; while (c = input()) { if (c == '\'') { if (!(c = input()) || (c != '\'')) { unput(); c = '\''; break; } } _dxfcclval.s[i++] = c; } _dxfcclval.s[i] = '\0'; if (c != '\'') { DXSetError(ERROR_BAD_PARAMETER, "Compute string has unmatched '"); LEX_RETURN(ERROR); } } LEX_RETURN(T_STRING); case '.': /* logical or float */ if (lastToken != T_INPUT && lastToken != T_RPAR && lastToken != T_NAME) { c = input(); if (isdigit(c)) { _dxfcctext[_dxfccleng++] = '.'; goto fraction; } unput(); } LEX_RETURN(T_PERIOD); case '0': /* octal or hex input */ _dxfcctext[_dxfccleng++] = c; c = input(); /* Process hex input. if there are more than 8 hex digits * (non-zero), then this won't fit in a 32 bit int. */ if (c == 'x' || c == 'X') { do { _dxfcctext[_dxfccleng++] = c; c = input(); } while (isxdigit(c)); _dxfcctext[_dxfccleng] = '\0'; if (_dxfccleng - strspn(_dxfcctext, "0x") > 8) { DXSetError(ERROR_BAD_PARAMETER, "#12080", _dxfcctext); LEX_RETURN(ERROR); } _dxfcclval.i = strtol(_dxfcctext, NULL, 0); } /* * Process octal, becoming float if we get ., e, or E * Note that we don't use strtol here because that doesn't * understand the C sense of '8' and '9' as octal digits. * If the we are about to multiply this number by 8, and it * is greater than or equal to 4Gig >> 3, then it's an error. */ else { _dxfcclval.i = 0; while (isdigit(c)) { if (c == '8' || c == '9') DXWarning ("bad octal digit `%c'", c); _dxfcctext[_dxfccleng++] = c; /* Check overflow (including carying the high bit of 8&9) */ if ((_dxfcclval.i + ((c - '0') >> 3)) >= 0x20000000) { DXSetError(ERROR_BAD_PARAMETER, "#12081", _dxfcctext); LEX_RETURN(ERROR); } _dxfcclval.i = _dxfcclval.i * 8 + (c - '0'); c = input(); } if (c == '.') { goto fraction; } else if (c == 'e' || c == 'E') goto exponent; } /* * Got something we didn't understand, quit (already converted) */ unput(); LEX_RETURN(T_INT); case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Decimal input */ isDouble = 0; do { _dxfcctext[_dxfccleng++] = c; c = input(); } while (isdigit(c)); if (c == '.') { goto fraction; } else if (c == 'e' || c == 'E') goto exponent; else if (c == 'd' || c == 'D') { c = 'e'; isDouble = 1; goto exponent; } unput(); _dxfcctext[_dxfccleng] = '\0'; if (strlen(_dxfcctext) > 10 || (strlen(_dxfcctext) == 10 && strcmp(_dxfcctext, "2147483647") > 0)) { DXSetError(ERROR_BAD_PARAMETER, "#12082", _dxfcctext); LEX_RETURN(ERROR); } _dxfcclval.i = strtol(_dxfcctext, NULL, 0); LEX_RETURN(T_INT); fraction: do { _dxfcctext[_dxfccleng++] = c; c = input(); if (c == 'e' || c == 'E') goto exponent; else if (c == 'd' || c == 'D') { c = 'e'; isDouble = 1; goto exponent; } } while (isdigit(c)); unput(); _dxfcctext[_dxfccleng] = '\0'; d = atof(_dxfcctext); if ((d > 0 && d > DXD_MAX_FLOAT) || (d < 0 && d < -DXD_MAX_FLOAT)) { DXSetError(ERROR_BAD_PARAMETER, "#12085", _dxfcctext); LEX_RETURN(ERROR); } else if ((d > 0 && d < DXD_MIN_FLOAT) || (d < 0 && d > -DXD_MIN_FLOAT)) { DXSetError(ERROR_BAD_PARAMETER, "#12085", _dxfcctext); LEX_RETURN(ERROR); } _dxfcclval.f = d; LEX_RETURN(T_FLOAT); exponent: /* Jam the 'e' in place and get the next thing. If it's the sign, * shove it in too. Then, suck up all digits. */ _dxfcctext[_dxfccleng++] = c; c = input(); if (c == '+' || c == '-') { _dxfcctext[_dxfccleng++] = c; c = input(); } while (isdigit(c)) { _dxfcctext[_dxfccleng++] = c; c = input(); } unput(); _dxfcctext[_dxfccleng] = '\0'; d = atof(_dxfcctext); if (!isDouble) { if ((d > 0 && d > DXD_MAX_FLOAT) || (d < 0 && d < -DXD_MAX_FLOAT)) { DXSetError(ERROR_BAD_PARAMETER, "#12085", _dxfcctext); LEX_RETURN(ERROR); } else if ((d > 0 && d < DXD_MIN_FLOAT) || (d < 0 && d > -DXD_MIN_FLOAT)) { DXSetError(ERROR_BAD_PARAMETER, "#12085", _dxfcctext); LEX_RETURN(ERROR); } _dxfcclval.f = d; LEX_RETURN(T_FLOAT); } else { _dxfcclval.d = d; LEX_RETURN(T_DOUBLE); } default: /* * most likely an identifier */ if (isalpha(c)) { do { _dxfcctext[_dxfccleng++] = c; c = input(); } while(isalpha(c) || isdigit(c) || c == '_'); unput(); _dxfcctext[_dxfccleng] = '\0'; /* check for keywords */ for (i=0; i < sizeof(keytab) / sizeof(keytab[0]); i++) if (strcmp(keytab[i].name, _dxfcctext) == 0) LEX_RETURN(keytab[i].value); strncpy (_dxfcclval.s, _dxfcctext, MAX_PARSE_STRING_SIZE); LEX_RETURN(T_NAME); } else { DXSetError(ERROR_BAD_PARAMETER, "#12095", c); LEX_RETURN(ERROR); } } } }