home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- CALEXPR.C
- (C) ¬⌐┼v 1988-1992 Autodesk ñ╜Ñq
-
- Ñ╗╡{ªíñwÑ╤ Autodesk ñ╜Ñq╡∙ÑU¬⌐┼v, ╢╚⌐≤ñU¡z▒í¬pñUÑi▒┬╗P▒zíu│\ÑiívíC
- ╗╒ñUñú▒oÑHÑ⌠ª≤º╬ªí╡oªµ⌐╬ÑX¬⌐ª╣╡{ªí¬║íu¡∞⌐l╜Xív; ª²ñ╣│\▒zªb»S⌐w¡lÑ═
- ¬║ñuº@ñW╡▓ªXª╣╡{ªí¬║íuÑ╪¬║╜Xív¿╧Ñ╬íCª│├÷│o├■¡lÑ═ñuº@¬║▒°Ñ≤ªpñU:
-
- ( i) │]¡pñW╗Pñuº@ñW¼╥»┬║Θ░w╣∩ Autodesk ñ╜Ñq¬║▓ú½~íC
- (ii) ╕ⁿª│íu¬⌐┼v (C) 1988-1992 Autodesk ñ╜Ñqív¬║¬⌐┼v│qºiíC
-
-
-
- AUTODESKñ╜Ñq┤ú¿╤ª╣╡{ªí╢╚¿╤º@íu├■ªⁿív¬║░╤ª╥, ª╙ÑBñú▒╞░úª│Ñ⌠ª≤┐∙╗~¬║
- Ñi»αíCAUTODESKñ╜Ñq»Sª╣º_╗{Ñ⌠ª≤»S⌐wÑ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºt
- ÑX¿π¬║½O├╥íCAUTODESKñ╜ÑqªP«╔ÑτñúÑX¿πª╣╡{ªí░⌡ªµ«╔ñ@⌐wñú╖|íuññ┬_ív⌐╬
- íuº╣Ñ■╡L╗~ív¬║½O├╥íC
-
-
- Description: The syntactic analysis of the expression based on
- the context-free LL(1) grammar.
-
- Notes:
-
- The syntax of the expression:
-
- EXPR = TERM + TERM ...
- TERM = POWER * POWER *...
- POWER = FACTOR ^ FACTOR ^...
- FACTOR = +- NUMBER
- VECTOR
- (EXPR)
- FUNC(EXPR,EXPR,...)
- ......
-
- VECTOR = [EXPR,EXPR,EXPR]
-
- *****************************************************************************/
-
-
- /****************************************************************************/
- /* INCLUDES */
- /****************************************************************************/
-
- #define R12_EXTLISPADS 1 /* Enable extended AutoLISP/ADS funcs */
-
- #include "cal.h"
-
-
- /****************************************************************************/
- /* STATIC FUNCTIONS */
- /****************************************************************************/
-
- static int check_overflow _((vector_real_int *value, int n));
- static void vector _((vector_real_int *value));
- static void AutoLISP_variable _((vector_real_int *value));
- static void factor _((vector_real_int *value));
- static void power _((vector_real_int *value));
- static void term _((vector_real_int *value));
- static void expr _((vector_real_int *value));
-
-
- /****************************************************************************/
- /*.doc check_overflow(internal)*/
- /*+
- Check whether overflow occured.
- -*/
- /****************************************************************************/
-
-
- static int
- /*FCN*/check_overflow(value, n)
-
- vector_real_int *value; /* The value to check */
- int n; /* Error to display if overflow */
- /* 0=Default error message */
- {
- if (cal_err)
- return(FALSE);
-
- if (n == 0) {
- n = 23; /* Default error message */
- }
-
- if ((errno == EDOM) || (errno == ERANGE)) {
- error(n, NULL);
- return(FALSE);
- }
- if (value->type == vector_type) {
- if ((value->v[X] == HUGE_VAL) ||
- (value->v[Y] == HUGE_VAL) ||
- (value->v[Z] == HUGE_VAL)) {
- error(n, NULL);
- return(FALSE);
- } else {
- return(TRUE);
- }
- } else if (value->r == HUGE_VAL) {
- error(n, NULL);
- return(FALSE);
- } else {
- return(TRUE);
- }
- } /*check_overflow*/
-
-
- /****************************************************************************/
- /*.doc vector(internal)*/
- /*+
- Parsing the nonterminal symbol VECTOR=[EXPR,EXPR,EXPR].
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/vector(value)
-
- vector_real_int *value;
- {
- ads_point v, c;
- double r, fi, theta;
- vector_real_int sub_expr;
- int cylindrical_cs, spherical_cs, relative_cs, world_cs;
- struct resbuf buff;
-
- if (cal_err)
- return;
-
- cylindrical_cs = spherical_cs = relative_cs = world_cs = FALSE;
- v[X] = v[Y] = v[Z] = 0.0;
-
- cal_next_symbol();
-
- if (cal_lex.sym == at_sym) {
- relative_cs = TRUE;
- cal_next_symbol();
- }
-
- if (cal_lex.sym == asterisk_sym) {
- world_cs = TRUE;
- cal_next_symbol();
- }
-
- if ((cal_lex.sym != comma_sym) &&
- (cal_lex.sym != lessthan_sym) &&
- (cal_lex.sym != rbracket_sym)) {
-
- expr(&sub_expr);
- if (cal_err)
- return;
-
- if ((sub_expr.type != real_type) &&
- (sub_expr.type != int_type)) {
- error(6, NULL);
- return;
- }
- v[X] = sub_expr.r;
- }
-
- if ((cal_lex.sym == comma_sym) || (cal_lex.sym == lessthan_sym)) {
- cylindrical_cs = (cal_lex.sym == lessthan_sym);
- cal_next_symbol();
-
- } else if (cal_lex.sym == rbracket_sym) {
- goto Vector_completed;
- } else {
- error(7, NULL);
- return;
- }
-
- if ((cal_lex.sym != comma_sym) &&
- (cal_lex.sym != lessthan_sym) &&
- (cal_lex.sym != rbracket_sym)) {
-
- expr(&sub_expr);
- if (cal_err)
- return;
-
- if ((sub_expr.type != real_type) &&
- (sub_expr.type != int_type)) {
- error(6, NULL);
- return;
- }
- v[Y] = sub_expr.r;
- }
-
- if ((cal_lex.sym == comma_sym) || (cal_lex.sym == lessthan_sym)) {
-
- spherical_cs = (cal_lex.sym == lessthan_sym);
- cal_next_symbol();
-
- } else if (cal_lex.sym == rbracket_sym) {
- goto Vector_completed;
- } else {
- error(7, NULL);
- return;
- }
-
- if (cal_lex.sym != rbracket_sym) {
-
- expr(&sub_expr);
-
- if (cal_err)
- return;
-
- if ((sub_expr.type != real_type) &&
- (sub_expr.type != int_type)) {
- error(6, NULL);
- return;
- }
- v[Z] = sub_expr.r;
- }
-
- Vector_completed:
-
- if (cal_lex.sym == rbracket_sym) {
- cal_next_symbol();
- } else {
- error(8, NULL);
- return;
- }
-
- value->type = vector_type;
-
- if (relative_cs) {
- ads_getvar("LASTPOINT", &buff);
-
- if (world_cs) {
- sa_u2w(buff.resval.rpoint, c);
- } else {
- CPY_PNT(c, buff.resval.rpoint);
- }
- } else {
- c[X] = c[Y] = c[Z] = 0.0;;
- }
-
- if (!cylindrical_cs && !spherical_cs) {
- ADD_PNT(v, c, v);
-
- } else if (cylindrical_cs && !spherical_cs) {
- r = v[X];
- fi = v[Y] * DEGRAD;
-
- v[X] = c[X] + r * cos(fi);
- v[Y] = c[Y] + r * sin(fi);
- v[Z] = c[Z] + v[Z];
-
- } else if (cylindrical_cs && spherical_cs) {
- r = v[X];
- fi = v[Y] * DEGRAD;
- theta = v[Z] * DEGRAD;
-
- v[X] = c[X] + r * cos(fi) * cos(theta);
- v[Y] = c[Y] + r * sin(fi) * cos(theta);
- v[Z] = c[Z] + r * sin(theta);
- } else {
- error(35, NULL);
- return;
- }
-
- if (world_cs) {
- sa_w2u(v, v);
- }
-
- CPY_PNT(value->v, v);
- check_overflow(value, 0);
-
- } /*vector*/
-
-
- /****************************************************************************/
- /*.doc AutoLISP_variable(internal)*/
- /*+
- Get value of AutoLISP variable.
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/AutoLISP_variable(value)
-
- vector_real_int *value;
- {
- struct resbuf *rb = NULL;
- int success;
-
- if (cal_err)
- return;
-
- success = ads_getsym(cal_lex.id, &rb);
-
- if ((success != RTNORM) || (rb == NULL)) {
- error(45, cal_lex.id);
- return;
- }
-
- /* Check the resbuf type */
-
- switch (rb->restype) {
-
- case RTSHORT:
- value->type = int_type;
- value->r = (double)rb->resval.rint;
- break;
- case RTREAL:
- value->type = real_type;
- value->r = rb->resval.rreal;
- break;
- case RTPOINT:
- case RT3DPOINT:
- value->type = vector_type;
- CPY_PNT(value->v, rb->resval.rpoint);
- break;
- default:
- error(43, cal_lex.id);
- return;
- } /*switch*/
-
- ads_relrb(rb);
- cal_next_symbol();
-
- } /*AutoLISP_variable*/
-
-
- /****************************************************************************/
- /*.doc factor(internal)*/
- /*+
- Parsing the nonterminal symbol FACTOR = NUMBER | FUNC() | VARIABLE |...
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/factor(value)
-
- vector_real_int *value;
- {
- vector_real_int f;
- int success;
- int is_minus;
-
- if (cal_err)
- return;
-
- /* Check the leading unary plus or minus */
-
- if (cal_lex.sym == minus_sym) {
- is_minus = TRUE;
- cal_next_symbol();
- } else if (cal_lex.sym == plus_sym) {
- cal_next_symbol();
- } else {
- is_minus = FALSE;
- }
-
- if (cal_lex.sym == ident_sym) {
- AutoLISP_variable(&f);
-
- } else if (cal_lex.sym == func_sym) {
-
- vector_real_int par[MAX_FUNC_PARAM];
- int nop;
- void (*func_ptr)();
- char func_name[MAX_SYMBOL_LENGTH+1];
- int i;
-
- func_ptr = cal_lex.func_ptr;
- strcpy(func_name, cal_lex.id);
- nop = 0;
- cal_next_symbol();
-
- if (cal_lex.sym == lparent_sym) {
- cal_next_symbol();
-
- while (!cal_err &&
- (cal_lex.sym != rparent_sym) &&
- (nop < MAX_FUNC_PARAM)) {
-
- expr(&par[nop++]);
-
- if (cal_lex.sym == comma_sym) {
- cal_next_symbol();
- } else if (cal_lex.sym != rparent_sym) {
- error(49, func_name);
- return;
- }
- } /*while*/
-
- if (cal_lex.sym != rparent_sym) {
- error(50, func_name);
- return;
- } else {
- cal_next_symbol();
- }
- } /*if*/
-
- if (cal_err)
- return;
-
- /* Pass the actual function arguments */
-
- no_of_params = nop;
- for (i = 0; i < nop; i++) {
- params[i] = par[i];
- }
-
- /* Call the function */
-
- (*func_ptr)();
- if (cal_err)
- return;
-
- f = result;
-
- } else if (cal_lex.sym == real_sym) {
- f.type = real_type;
- f.r = cal_lex.real_num;
- cal_next_symbol();
-
- } else if (cal_lex.sym == int_sym) {
- f.type = int_type;
- f.r = cal_lex.real_num;
- cal_next_symbol();
-
- } else if (cal_lex.sym == pi_sym) {
- f.type = real_type;
- f.r = PI;
- cal_next_symbol();
-
- } else if (cal_lex.sym == getvar_sym) {
- struct resbuf buff;
-
- cal_next_symbol();
- if (cal_lex.sym != lparent_sym) {
- error(26, "GETVAR(AutoCAD_system_variable)");
- return;
- }
-
- cal_next_symbol();
- if (cal_lex.sym != ident_sym) {
- error(26, "GETVAR(AutoCAD_system_variable)");
- return;
- }
- success = ads_getvar(cal_lex.id, &buff);
- if (success != RTNORM) {
- error(32, cal_lex.id);
- return;
- }
-
- switch (buff.restype) {
-
- case RTPOINT:
- case RT3DPOINT:
- f.type = vector_type;
- CPY_PNT(f.v, buff.resval.rpoint);
- break;
- case RTREAL:
- case RTANG:
- case RTORINT:
- f.type = real_type;
- f.r = buff.resval.rreal;
- break;
- case RTSHORT:
- f.type = int_type;
- f.r = buff.resval.rint;
- break;
- case RTLONG:
- f.type = int_type;
- f.r = buff.resval.rlong;
- break;
- default:
- if (buff.restype == RTSTR)
- free(buff.resval.rstring);
- error(33, NULL);
- return;
- } /*switch*/
-
- cal_next_symbol();
- if (cal_lex.sym != rparent_sym) {
- error(5, NULL);
- return;
- }
- cal_next_symbol();
-
- } else if (cal_lex.sym == cvunit_sym) {
- char from_unit[MAX_LINE_LENGTH];
- char to_unit[MAX_LINE_LENGTH];
-
- cal_next_symbol();
- if (cal_lex.sym != lparent_sym) {
- error(63, NULL);
- return;
- }
- cal_next_symbol();
-
- expr(&f);
- if (cal_err)
- return;
-
- if (cal_lex.sym != comma_sym) {
- error(63, NULL);
- return;
- }
-
- cal_next_symbol();
- if (cal_lex.sym != ident_sym) {
- error(63, NULL);
- return;
- }
-
- strcpy(from_unit, cal_lex.id);
-
- cal_next_symbol();
- if (cal_lex.sym != comma_sym) {
- error(63, NULL);
- return;
- }
-
- cal_next_symbol();
- if (cal_lex.sym != ident_sym) {
- error(63, NULL);
- return;
- }
-
- strcpy(to_unit, cal_lex.id);
-
- cal_next_symbol();
- if (cal_lex.sym != rparent_sym) {
- error(63, NULL);
- return;
- }
-
- switch (f.type) {
-
- case real_type:
- case int_type:
- f.type = real_type;
- success = ads_cvunit(f.r, from_unit, to_unit, &f.r);
- break;
- case vector_type:
- success = ads_cvunit(f.v[X], from_unit, to_unit, &f.v[X]);
- if (success != RTNORM)
- break;
- success = ads_cvunit(f.v[Y], from_unit, to_unit, &f.v[Y]);
- if (success != RTNORM)
- break;
- success = ads_cvunit(f.v[Z], from_unit, to_unit, &f.v[Z]);
- if (success != RTNORM)
- break;
- break;
- default:
- return;
- } /*switch*/
-
- if (success != RTNORM) {
- error(64, NULL);
- return;
- }
- cal_next_symbol();
-
- } else if (cal_lex.sym == at_sym) {
- struct resbuf buff;
-
- f.type = vector_type;
- ads_getvar("LASTPOINT", &buff);
- CPY_PNT(f.v, buff.resval.rpoint);
- cal_next_symbol();
-
- } else if (cal_lex.sym == lparent_sym) {
- cal_next_symbol();
- expr(&f);
- if (cal_err)
- return;
- if (cal_lex.sym == rparent_sym) {
- cal_next_symbol();
- } else {
- error(5, NULL);
- return;
- }
-
- } else if (cal_lex.sym == lbracket_sym) {
- vector(&f);
- } else if (cal_lex.sym == no_sym) {
- error(9, NULL);
- return;
- } else {
- error(10, NULL);
- return;
- }
-
- check_overflow(&f, 0);
-
- if (cal_err)
- return;
-
- if (is_minus) {
- if (f.type == vector_type) {
- f.v[X] = -f.v[X];
- f.v[Y] = -f.v[Y];
- f.v[Z] = -f.v[Z];
- } else {
- f.r = -f.r;
- }
- }
-
- *value = f;
- } /*factor*/
-
-
- /****************************************************************************/
- /*.doc power(internal)*/
- /*+
- Parsing the nonterminal symbol POWER = FACTOR^FACTOR^...
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/power(value)
-
- vector_real_int *value;
- {
- vector_real_int p, f;
-
- if (cal_err)
- return;
-
- factor(&p);
-
- if (cal_err)
- return;
-
- while (cal_lex.sym == caret_sym) {
- cal_next_symbol();
- factor(&f);
- if (cal_err)
- return;
- if ((p.type == vector_type) || (f.type == vector_type)) {
- error(16, NULL);
- return;
- }
-
- p.type = real_type;
-
- if (p.r == 0.0) {
- ; /*p.r = 0.0*/
- } else if (f.r == 0.0) {
- p.r = 1.0;
- } else {
- if ((p.r < 0.0) && (f.r != (int)f.r)) {
- error(17, NULL);
- return;
- }
- p.r = pow(p.r, f.r);
- if (!check_overflow(&p, 25))
- return;
- }
- } /*while*/
-
- check_overflow(&p, 0);
-
- *value = p;
- } /*power*/
-
-
- /****************************************************************************/
- /*.doc term(internal)*/
- /*+
- Parsing the nonterminal symbol TERM = POWER*POWER*...
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/term(value)
-
- vector_real_int *value;
- {
- vector_real_int t, p, tmp;
- symbol_type oper;
-
- if (cal_err)
- return;
-
- power(&t);
- if (cal_err)
- return;
-
- while ((cal_lex.sym == asterisk_sym) ||
- (cal_lex.sym == slash_sym) ||
- (cal_lex.sym == ampersand_sym)) {
-
- oper = cal_lex.sym;
- cal_next_symbol();
- power(&p);
-
- if (cal_err)
- return;
-
- switch (oper) {
-
- case asterisk_sym:
- if ((t.type != vector_type) && (p.type != vector_type)) {
- if (p.type == real_type) {
- t.type = real_type;
- }
- t.r *= p.r;
-
- } else if ((t.type == vector_type) && (p.type == vector_type)) {
- t.type = real_type;
- t.r = DOTPROD(t.v, p.v);
-
- } else if ((t.type == vector_type) && (p.type != vector_type)) {
- t.type = vector_type;
- t.v[X] *= p.r;
- t.v[Y] *= p.r;
- t.v[Z] *= p.r;
- } else {
- t.type = vector_type;
- t.v[X] = p.v[X] * t.r;
- t.v[Y] = p.v[Y] * t.r;
- t.v[Z] = p.v[Z] * t.r;
- }
- break;
-
- case slash_sym:
- if (fabs(p.r) < EPS) {
- error(18, NULL);
- return;
- }
- if ((t.type != vector_type) && (p.type != vector_type)) {
- t.type = real_type;
- t.r /= p.r;
-
- } else if ((t.type == vector_type) && (p.type != vector_type)) {
- t.v[X] /= p.r;
- t.v[Y] /= p.r;
- t.v[Z] /= p.r;
- } else {
- error(19, NULL);
- return;
- }
- break;
-
- case ampersand_sym: /*Cross product*/
- if ((t.type == vector_type) && (p.type == vector_type)) {
- tmp.type = vector_type;
- tmp.v[X] = t.v[Y] * p.v[Z] - t.v[Z] * p.v[Y];
- tmp.v[Y] = t.v[Z] * p.v[X] - t.v[X] * p.v[Z];
- tmp.v[Z] = t.v[X] * p.v[Y] - t.v[Y] * p.v[X];
- t = tmp;
- } else {
- error(20, NULL);
- return;
- }
- break;
- } /*switch*/
-
- if(!check_overflow(&t, 0))
- return;
- } /*while*/
-
- check_overflow(&t, 0);
-
- *value = t;
- } /*term*/
-
-
- /****************************************************************************/
- /*.doc expr(internal)*/
- /*+
- Parsing the nonterminal symbol EXPR = TERM+TERM+...
- -*/
- /****************************************************************************/
-
-
- static void
- /*FCN*/expr(value)
-
- vector_real_int *value;
- {
- vector_real_int e, t;
- symbol_type oper;
-
- if (cal_err)
- return;
-
- term(&e);
- if (cal_err)
- return;
-
- while ((cal_lex.sym == plus_sym) || (cal_lex.sym == minus_sym)) {
-
- oper = cal_lex.sym;
- cal_next_symbol();
-
- term(&t);
-
- if (cal_err)
- return;
-
- switch (oper) {
-
- case plus_sym:
- if ((e.type != vector_type) && (t.type != vector_type)) {
- if (t.type == real_type) {
- e.type = real_type;
- }
- e.r += t.r;
-
- } else if ((e.type == vector_type) && (t.type == vector_type)) {
- ADD_PNT(e.v, e.v, t.v);
- } else {
- error(21, NULL);
- return;
- }
- break;
-
- case minus_sym:
- if ((e.type != vector_type) && (t.type != vector_type)) {
- if (t.type == real_type) {
- e.type = real_type;
- }
- e.r -= t.r;
-
- } else if ((e.type == vector_type) && (t.type == vector_type)) {
- SUB_PNT(e.v, e.v, t.v);
- } else {
- error(21, NULL);
- return;
- }
- } /*switch*/
-
- if (!check_overflow(&e, 0))
- return;
- } /*while*/
-
- check_overflow(&e, 0);
-
- *value = e;
- } /*expr*/
-
-
- /****************************************************************************/
- /*.doc cal_evaluate_expression(external)*/
- /*+
- The top-level expression-evalution function.
-
- The function returns TRUE if succeeds, or FALSE if it fails.
- -*/
- /****************************************************************************/
-
-
- int
- /*FCN*/cal_evaluate_expression(line, value)
-
- char *line; /* Input expression as a string */
- vector_real_int *value; /* Returned value of expression */
- {
- vector_real_int val;
- char id[MAX_SYMBOL_LENGTH+1];
- struct resbuf rb;
- int success;
-
- cal_lex_start(line);
-
- /* Check whether the expression begins with 'VAR=' assignment */
-
- id[0] = EOS;
- if (cal_lex.sym == ident_sym) {
- strcpy(id, cal_lex.id); /* It might be assignment */
- cal_next_symbol();
- if (cal_err)
- return(FALSE);
-
- if (cal_lex.sym != equal_sym) {
- id[0] = EOS; /* No, it isn't assignment */
- cal_lex_start(line);
- } else {
- cal_next_symbol();
- }
- }
- if (cal_err)
- return(FALSE);
-
- expr(&val); /* Start the expression evaluation */
-
- if (cal_err)
- return(FALSE);
-
- if (cal_lex.sym != no_sym) {
- error(10, NULL);
- return(FALSE);
- }
-
- if ((val.type == int_type) &&
- ((val.r > 32767) || (val.r < -32768))) {
- error(41, NULL);
- return(FALSE);
- }
-
- /* Assign value of expression to AutoLISP variable, if available */
-
- if (id[0] != EOS) {
- switch (val.type) {
- case int_type:
- rb.restype = RTSHORT;
- rb.resval.rint = (int)val.r;
- break;
- case real_type:
- rb.restype = RTREAL;
- rb.resval.rreal = val.r;
- break;
- case vector_type:
- rb.restype = RT3DPOINT;
- CPY_PNT(rb.resval.rpoint, val.v);
- break;
- default:
- error(-443, NULL);
- return(FALSE);
- } /*switch*/
-
- rb.rbnext = NULL;
-
- success = ads_putsym(id, &rb);
- if (success != RTNORM) {
- error(29, id);
- return(FALSE);
- }
- } /*if*/
-
- *value = val;
- return(TRUE);
- } /*evaluate_expression*/
-
-