/******************************************************************** This file is part of the abs 0.907 distribution. abs is a spreadsheet with graphical user interface. Copyright (C) 1998-2001 André Bertin (Andre.Bertin@ping.be) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version if in the same spirit as version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Concact: abs@pi.be http://home.pi.be/bertin/abs.shtml *********************************************************************/ #include #include "interpret.h" #include "y.tab.h" #include "oper.h" #include "symboltable.h" #include "libfct.h" #include "properties.h" #include "project.h" #include "io.h" #include "abv.h" static nodeType ***argnode = NULL; static obj **argu = NULL; static obj **arguref = NULL; static int *nargnode = NULL; static int routinedeep = -1; static int initconst = 0; static int dobreak = 0; void cb_Break () { dobreak = 1; fprintf (stderr, "Break!\n"); return; } void resetbreak () { dobreak = 0; return; } int settype (nodeType * p) { if (p != NULL) { int type = p->opr.oper.rec.i; if (type == NEW) { symbol_settype (type, 1); } else { symbol_settype (type, 0); } } else symbol_settype (VARIANT, 0); return 0; } static int scope = 1; int setscope (int a) { scope = a; return 0; } int setcstscope (nodeType * p) { if (p != NULL) { int sc = p->opr.oper.rec.i; if (sc == PRIVATE) { scope = 4; } else { scope = 2; } } else symbol_settype (VARIANT, 0); return 0; } static int Transmit = BYREF; static int settransmit (nodeType * p) { if (p != NULL) { int mode = p->opr.oper.rec.i; if (mode == BYVAL) { Transmit = BYVAL; } else { Transmit = BYREF; } } else Transmit = BYREF; return 0; } static char * setfilemode (nodeType * p) { char *ret = "rw"; int mode = p->opr.oper.rec.i; if (mode == APPEND) ret = "a+"; if (mode == BINARY) ret = "r+b"; if (mode == INPUT) ret = "r"; if (mode == OUTPUT) ret = "w"; if (mode == RANDOM) ret = "r+"; return ret; } obj exdecl (nodeType * p) { obj o; if (dobreak) return o; if (!p) return o; switch (p->type) { case typeCon: { return p->con.value; } case typeMember: { o = p->member.member; if (o.type == MEMBER) { o.type = classname2classpos (o.label); if (o.type == -1) o.type = MEMBER; } return o; } case typeId: { Idval *val; if (p->id.id.type == BUILTINFUNCTION) { o = check4property (p->id.id); if (o.type != BUILTINFUNCTION) return o; } if (p->id.id.type == PROPERTY) { o = property2obj (p->id.id); return o; } val = look (p->id.id.label, 1); o.rec.s = (char *) val; o.type = p->id.id.type; o.label = p->id.id.label; return o; } case typeOpr1: switch (p->opr1.oper.rec.i) { case UMINUS: return mkuminus (exdecl (p->opr1.op1)); } case typeOpr2: switch (p->opr2.oper.rec.i) { case '=': { obj o1 = exdecl (p->opr2.op2); obj o0 = exdecl (p->opr2.op1); o = mkassign (o0, o1); freenocstobj (o1); return o; } case '+': { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mksum (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '-': { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mkdiff (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '*': { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mkmult (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '/': { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mkdiv (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case MOD: { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mkmod (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '\\': { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mkintdiv (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '^': { obj o1, o2, o3; o1 = exdecl (p->opr2.op1); o2 = exdecl (p->opr2.op2); o3 = mkpow (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } } case typeOpr: switch (p->opr.oper.rec.i) { case NEWLINE: { int i; int nops = p->opr.nops; for (i = 0; i < nops; i++) { exdecl (p->opr.op[i]); } return o; } case IDLIST: { int nops = p->opr.nops; Idval *val; nodeType *pp; if (nops == 5) { exdecl (p->opr.op[0]); settype (p->opr.op[3]); pp = p->opr.op[1]; val = look (pp->id.id.label, scope); symbol_settype (VARIANT, 0); if (initconst && p->opr.op[4] != NULL) { obj o; o.rec.s = (char *) val; pp = p->opr.op[4]; o1eqo2 (&o, exdecl (pp)); val->protect = 1; } } else { settype (p->opr.op[2]); pp = p->opr.op[0]; val = look (pp->id.id.label, scope); symbol_settype (VARIANT, 0); if (initconst && p->opr.op[3] != NULL) { obj o; o.rec.s = (char *) val; pp = p->opr.op[3]; o1eqo2 (&o, exdecl (pp)); val->protect = 1; } } return o; } case CONST: { int nops = p->opr.nops; initconst = 1; if (nops == 2) { nodeType *pp = p->opr.op[0]; int sc = pp->opr.oper.rec.i; if (sc == PUBLIC) setscope (2); else setscope (4); exdecl (p->opr.op[1]); } else { setscope (4); exdecl (p->opr.op[0]); } setscope (1); initconst = 0; return o; } case DIM: { setscope (2); exdecl (p->opr.op[0]); setscope (1); return o; } case PUBLIC: { setscope (4); exdecl (p->opr.op[0]); setscope (1); return o; } case PRIVATE: { setscope (2); exdecl (p->opr.op[0]); setscope (1); return o; } case '.': { switch (p->opr.nops) { case 1: { } case 2: { return mkderef (exdecl (p->opr.op[0]), exdecl (p->opr.op[1])); } } return o; } } } return o; } static nodeType *selexpr[20]; static int caseelse[20]; static int nsel = -1; obj exint (nodeType * p) { obj o; if (!p) return o; switch (p->type) { case typeCon: { return p->con.value; } case typeMember: { o = p->member.member; if (o.type == MEMBER) { o.type = classname2classpos (o.label); if (o.type == -1) o.type = MEMBER; } return o; } case typeId: { Idval *val; if (p->id.id.type == BUILTINFUNCTION) { o = check4property (p->id.id); if (o.type != BUILTINFUNCTION) return o; } if (p->id.id.type == PROPERTY) { o = property2obj (p->id.id); return o; } val = look (p->id.id.label, scope); o.rec.s = (char *) val; o.type = p->id.id.type; o.label = p->id.id.label; return o; } case typeOpr1: switch (p->opr1.oper.rec.i) { case UMINUS: return mkuminus (exint (p->opr1.op1)); } case typeOpr2: switch (p->opr2.oper.rec.i) { case '=': { obj o1 = exint (p->opr2.op2); obj o0 = exint (p->opr2.op1); o = mkassign (o0, o1); freenocstobj (o1); return o; } case '+': { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mksum (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '-': { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mkdiff (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '*': { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mkmult (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '/': { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mkdiv (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case MOD: { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mkmod (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '\\': { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mkintdiv (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '^': { obj o1, o2, o3; o1 = exint (p->opr2.op1); o2 = exint (p->opr2.op2); o3 = mkpow (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } } case typeOpr: switch (p->opr.oper.rec.i) { case WHILE: { while (obj2double (exint (p->opr.op[0]))) { exint (p->opr.op[1]); } return o; } case UNTIL: { while (!obj2double (exint (p->opr.op[0]))) { exint (p->opr.op[1]); } return o; } case LOOPWHILE: { do { exint (p->opr.op[1]); } while (obj2double (exint (p->opr.op[0]))); return o; } case LOOPUNTIL: { do { exint (p->opr.op[1]); } while (!obj2double (exint (p->opr.op[0]))); return o; } case SELECT: { nsel++; if (nsel > 19) { fprintf (stderr, "Select case inside other one limited to 20 levels!\n"); nsel--; return o; } selexpr[nsel] = p->opr.op[0]; caseelse[nsel] = 1; exint (p->opr.op[1]); nsel--; return o; } case CASE: { switch (p->opr.nops) { case 2: if (objcmp (exint (selexpr[nsel]), exint (p->opr.op[0]))) { exint (p->opr.op[1]); caseelse[nsel] = 0; } break; case 3: exint (p->opr.op[0]); if (objcmp (exint (selexpr[nsel]), exint (p->opr.op[1]))) { exint (p->opr.op[2]); caseelse[nsel] = 0; } } return o; } case CASEELSE: { switch (p->opr.nops) { case 1: if (caseelse[nsel]) exint (p->opr.op[0]); break; case 2: exint (p->opr.op[0]); if (caseelse[nsel]) exint (p->opr.op[1]); } return o; } case FOR: { int negstep = 0; if (p->opr.nops > 5 && obj2double (exint (p->opr.op[3])) < 0) negstep = 1; else if (p->opr.nops < 6 && obj2double (exint (p->opr.op[1])) > obj2double (exint (p->opr.op[2]))) negstep = 1; o = mkassign (exint (p->opr.op[0]), (exint (p->opr.op[1]))); if (!negstep) { while (obj2int (mkle (exint (p->opr.op[0]), (exint (p->opr.op[2]))))) { if (p->opr.nops > 5) { o = exint (p->opr.op[4]); mksumassign (exint (p->opr.op[0]), exint (p->opr.op[3])); } else { o = exint (p->opr.op[3]); mkplusplus (exint (p->opr.op[0])); } } } else { while (obj2int (mkge (exint (p->opr.op[0]), (exint (p->opr.op[2]))))) { if (p->opr.nops > 5) { o = exint (p->opr.op[4]); mksumassign (exint (p->opr.op[0]), exint (p->opr.op[3])); } else { o = exint (p->opr.op[3]); mkminusminus (exint (p->opr.op[0])); } } } return o; }; case EACH: { int start = 1; int end = 0; obj index; obj collection = exint (p->opr.op[1]); end = obj2int ((arrayclass[collection.type].data[0].getfct) ()); index.type = INTEGER; for (index.rec.i = start; index.rec.i <= end; index.rec.i++) { mkassign (exint (p->opr.op[0]), (arrayclass[collection.type].fct[0].fct) (1, &index)); o = exint (p->opr.op[2]); } return o; }; case IF: { if (obj2double (exint (p->opr.op[0]))) o = exint (p->opr.op[1]); else if (p->opr.nops > 2) o = exint (p->opr.op[2]); return o; } case IDLIST: { int nops = p->opr.nops; Idval *val; nodeType *pp; if (nops == 5) { exint (p->opr.op[0]); settype (p->opr.op[3]); pp = p->opr.op[1]; val = look (pp->id.id.label, scope); symbol_settype (VARIANT, 0); if (initconst && p->opr.op[4] != NULL) { obj o; o.rec.s = (char *) val; pp = p->opr.op[4]; o1eqo2 (&o, exint (pp)); val->protect = 1; } } else { settype (p->opr.op[2]); pp = p->opr.op[0]; val = look (pp->id.id.label, scope); symbol_settype (VARIANT, 0); if (initconst && p->opr.op[3] != NULL) { obj o; o.rec.s = (char *) val; pp = p->opr.op[3]; o1eqo2 (&o, exint (pp)); val->protect = 1; } } return o; } case CONST: { int nops = p->opr.nops; initconst = 1; setscope (2); exint (p->opr.op[nops - 1]); setscope (1); initconst = 0; return o; } case DIM: { setscope (2); exint (p->opr.op[0]); setscope (1); return o; } case STATIC: { setscope (3); exint (p->opr.op[0]); setscope (1); return o; } case SUB: { argsub (); if (p->opr.op[1] != NULL) exint (p->opr.op[1]); exint (p->opr.op[2]); return o; } case CALL: { argcall (); exint (p->opr.op[1]); switch ((p->opr.op[0])->id.id.type) { case IDENTIFIER: { o = mkcall (exint (p->opr.op[0])); argendcall (); break; } case BUILTINFUNCTION: { o = mkcallbuiltin ((p->opr.op[0])->id.id); argendcallbuiltin (); break; } } return o; } case WITH: { withenter (exint (p->opr.op[0])); o = exint (p->opr.op[1]); withend (); return o; } case ARG: { switch (p->opr.nops) { case 1: { mkarg (p->opr.op[0]); return o; } case 2: { o = exint (p->opr.op[0]); mkarg (p->opr.op[1]); return o; } } return o; } case SUBARG: { switch (p->opr.nops) { case 3: { settransmit (p->opr.op[0]); settype (p->opr.op[2]); setscope (2); mkarg (p->opr.op[1]); symbol_settype (VARIANT, 0); setscope (1); return o; } case 4: { o = exint (p->opr.op[0]); settransmit (p->opr.op[1]); settype (p->opr.op[3]); setscope (2); mkarg (p->opr.op[2]); symbol_settype (VARIANT, 0); setscope (1); return o; } } return o; } case BUILTINFUNCTION: { argcall (); exint (p->opr.op[1]); o = mkcallbuiltin ((p->opr.op[0])->id.id); argendcallbuiltin (); return o; } case NEWLINE: { int i; int nops = p->opr.nops; for (i = 0; i < nops; i++) { exint (p->opr.op[i]); } return o; } case OPEN: { o.rec.i = io_open (obj2string (exint (p->opr.op[0])), setfilemode (p->opr.op[1]), obj2int (exint (p->opr.op[2]))); o.type = INTEGER; return o; }; case CLOSE: { o.rec.i = io_close (obj2int (exint (p->opr.op[0]))); o.type = INTEGER; return o; }; case SPC: { o.rec.i = obj2int (exint (p->opr.op[0])); o.type = INTEGER; return o; }; case TAB: { o.rec.i = -obj2int (exint (p->opr.op[0])); o.type = INTEGER; return o; }; case PRINT: { int tabspc = 0; if (p->opr.op[1] != NULL) tabspc = obj2int (exint (p->opr.op[1])); argcall (); exint (p->opr.op[2]); o.rec.i = io_print (obj2int (exint (p->opr.op[0])), tabspc, nargnode[routinedeep], argu[routinedeep]); argendcallbuiltin (); o.type = INTEGER; return o; }; case WRITE: { argcall (); exint (p->opr.op[1]); o.rec.i = io_write (obj2int (exint (p->opr.op[0])), nargnode[routinedeep], argu[routinedeep]); argendcallbuiltin (); o.type = INTEGER; return o; }; case INPUT: { int i; argcall (); exint (p->opr.op[1]); for (i = 0; i < nargnode[routinedeep]; i++) { argu[routinedeep][i] = io_input (obj2int (exint (p->opr.op[0]))); } argsub (); return exint (p->opr.op[1]); argendcall (); }; case LT: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mklt (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case GT: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkgt (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case GE: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkge (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case LE: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkle (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case NE: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkne (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case EQ: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkeq (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case OR: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkor (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case AND: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkand (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case XOR: { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkxor (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case '&': { obj o1, o2, o3; o1 = exint (p->opr.op[0]); o2 = exint (p->opr.op[1]); o3 = mkconcat (o1, o2); freenocstobj (o1); freenocstobj (o2); return o3; } case NOT: { obj o1, o3; o1 = exint (p->opr.op[0]); o3 = mknot (o1); freenocstobj (o1); return o3; } case BASEOBJECT: { return check_with ((p->opr.op[0])->id.id); } case RETURNOBJECT: { o = exint (p->opr.op[0]); return mkderef (o, exint (p->opr.op[1])); }; case ALONEOBJ: { o = exint (p->opr.op[0]); o = mkcallalone (o); return o; } case MEMBERFUNCTION: { exint (p->opr.op[1]); o = (exint (p->opr.op[0])); o.type = MEMBERFUNCTION; return o; } case OBJMEMBERFCT: { obj base = exint (p->opr.op[0]); argcall (); o = exint (p->opr.op[1]); o = mkcallmember (base, o); argendcall (); return o; } case FCTMEMBERFCT: { obj base = exint (p->opr.op[0]); argcall (); o = exint (p->opr.op[1]); o = mkcallmember (base, o); argendcall (); return o; } case '.': { switch (p->opr.nops) { case 1: { } case 2: { return mkderef (exint (p->opr.op[0]), exint (p->opr.op[1])); } } return o; } } } return o; } obj mkcall (obj identifier) { if (identifier.type == IDENTIFIER) { gotolabel (identifier.label); } return id2val (identifier); } typedef enum { call, sub } Arg_use; static Arg_use arg_use; int argsub () { arg_use = sub; return 0; } int argcall () { arg_use = call; routinedeep++; argnode = (nodeType ***) absrealloc (argnode, sizeof (nodeType **) * (routinedeep + 1), "argcall:argnode "); argu = (obj **) absrealloc (argu, sizeof (obj *) * (routinedeep + 1), "argcall:argu "); arguref = (obj **) absrealloc (arguref, sizeof (obj *) * (routinedeep + 1), "argcall:arguref "); nargnode = (int *) absrealloc (nargnode, sizeof (int) * (routinedeep + 1), "argcall:nargnode"); argnode[routinedeep] = NULL; argu[routinedeep] = NULL; arguref[routinedeep] = NULL; nargnode[routinedeep] = 0; return 0; } int argendcall () { arg_use = sub; if (argnode[routinedeep] != NULL) absfree (argnode[routinedeep], "argendcall:argnode[routinedeep]"); if (argu[routinedeep] != NULL) absfree (argu[routinedeep], "argendcall:argu [routinedeep]"); if (arguref[routinedeep] != NULL) absfree (arguref[routinedeep], "argendcall:arguref[routinedeep]"); routinedeep--; if (routinedeep < 0) { absfree (argnode, "argendcall:argnode "); argnode = NULL; absfree (argu, "argendcall:argu "); argu = NULL; absfree (arguref, "argendcall:arguref "); arguref = NULL; absfree (nargnode, "argendcall:nargnode"); nargnode = NULL; } else { argnode = (nodeType ***) absrealloc (argnode, sizeof (nodeType **) * (routinedeep + 1), "argcall:argnode "); argu = (obj **) absrealloc (argu, sizeof (obj *) * (routinedeep + 1), "argcall:argu "); arguref = (obj **) absrealloc (arguref, sizeof (obj *) * (routinedeep + 1), "argcall:arguref "); nargnode = (int *) absrealloc (nargnode, sizeof (int) * (routinedeep + 1), "argcall:nargnode"); } return 0; } int argendcallbuiltin () { argendcall (); arg_use = call; return 0; } obj mkarg (nodeType * arg) { obj o, id; int i; int narg; if (arg_use == call) { narg = nargnode[routinedeep]; argnode[routinedeep] = (nodeType **) absrealloc (argnode[routinedeep], sizeof (nodeType *) * (narg + 1), "mkarg:argnode"); argu[routinedeep] = (obj *) absrealloc (argu[routinedeep], sizeof (obj) * (narg + 1), "mkarg:argu "); arguref[routinedeep] = (obj *) absrealloc (arguref[routinedeep], sizeof (obj) * (narg + 1), "mkarg:arguref"); argnode[routinedeep][narg] = arg; argu[routinedeep][narg] = id2val (exint (arg)); arguref[routinedeep][narg] = exint (arg); nargnode[routinedeep]++; } else { nargnode[routinedeep]--; if (nargnode[routinedeep] >= 0) { o = argu[routinedeep][0]; id = arguref[routinedeep][0]; for (i = 0; i < nargnode[routinedeep]; i++) { argu[routinedeep][i] = argu[routinedeep][i + 1]; arguref[routinedeep][i] = arguref[routinedeep][i + 1]; } if (id.type == IDENTIFIER && Transmit == BYREF) setrefid (id); else unsetrefid (); return mkassign (exint (arg), o); } } return o; } obj mkcallbuiltin (obj identifier) { obj o; int narg; obj arg[10]; int i; narg = nargnode[routinedeep]; for (i = 0; i < nargnode[routinedeep]; i++) arg[i] = argu[routinedeep][i]; if (identifier.type == BUILTINFUNCTION) { o = (arrayfct[identifier.rec.i].fct) (narg, arg); } return o; } obj mkcallmember (base, identifier) obj base, identifier; { obj o; int narg; obj arg[10]; int i, found; if (base.type == IDENTIFIER) base = id2val (base); narg = nargnode[routinedeep]; for (i = 0; i < narg; i++) arg[i + 1] = argu[routinedeep][i]; narg++; arg[0] = base; found = 0; i = 0; if (base.type > NUMBER_OF_CLASS || base.type < 0) { fprintf (stderr, "unknown class %s type %d\n", base.label, base.type); return o; } while (arrayclass[base.type].fct[i].name != NULL && found == 0) { if (strcasecmp (identifier.label, arrayclass[base.type].fct[i].name) == 0) found = 1; i++; } i--; if (found) { o = (arrayclass[base.type].fct[i].fct) (narg, arg); } else { fprintf (stderr, "function %s is not member of type %d\n", identifier.label, base.type); printobj (base); } return o; } obj mkcallalone (member) obj member; { obj o; int narg; obj arg[10]; obj base; int i, found; if (member.type == MEMBER) base = *((obj *) member.rec.s); else return o; narg = 1; arg[0] = base; found = 0; i = 0; if (base.type > NUMBER_OF_CLASS || base.type < 0) { fprintf (stderr, "unknown class %s type %d\n", base.label, base.type); return o; } while (arrayclass[base.type].fct[i].name != NULL && found == 0) { if (strcasecmp (member.label, arrayclass[base.type].fct[i].name) == 0) found = 1; i++; } i--; if (found) { o = (arrayclass[base.type].fct[i].fct) (narg, arg); } else fprintf (stderr, "function %s is not member of type %d\n", member.label, base.type); return o; }