/******************************************************************** 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 "object.h" #include #include #include "class.h" #include "y.tab.h" #include "libfct.h" #include "memory.h" #include "properties.h" #include "symboltable.h" #include "cell.h" #include "range.h" #include "util.h" int str2int (str) char *str; { int ret, v; int pos = 0; int spc = 0; if (str == NULL) return 0; if (strlen (str) < 1) return 0; while (str[pos] == ' ' && pos < 256) { pos++; spc++; if (str[pos] == '\0') return 0; } if (isnumber (str[pos]) >= 0) { sscanf (str, "%d", &ret); return ret; } ret = 0; while (pos < 32 + spc) { v = isletter (str[pos]); if (v) { ret = ret * 26 + v; pos++; } else { return ret; } } return 0; } obj obj2oper (o) obj o; { obj o1 = o; return o1; } obj id2val (o) obj o; { if (o.type == IDENTIFIER || o.type == CONST) { obj *idval = &((Idval *) o.rec.s)->val; if (idval->type == VARIANT) idval = (obj *) idval->rec.s; return *idval; } return o; } obj obj2val (obj o) { obj o1 = id2val (o); switch (o1.type) { case INTEGER: break; case DOUBLE: break; case STRING_CONSTANT: break; case STRING: o1.type = STRING_CONSTANT; break; case CELL: o1 = cell_getobj ((Cell *) o1.rec.s); break; default: o1 = class2obj (o1); break; } return o1; } int obj2int (o) obj o; { int ret = 0; obj o1 = obj2val (o); switch (o1.type) { case DOUBLE: ret = o1.rec.d; break; case INTEGER: ret = o1.rec.i; break; case STRING_CONSTANT: { ret = str2int (o1.rec.s); } } return ret; } double obj2double (o) obj o; { double ret = 0.0; obj o1 = obj2val (o); switch (o1.type) { case DOUBLE: ret = o1.rec.d; break; case INTEGER: ret = o1.rec.i; break; case STRING_CONSTANT: { ret = str2int (o1.rec.s); } } return ret; } int objisstring (obj o) { obj o1 = obj2val (o); if (o1.type == STRING || o1.type == STRING_CONSTANT) return 1; return 0; } char * obj2string (o) obj o; { char *ret = NULL; obj o1 = obj2val (o); if (o1.type == CELL) o1 = cell_getobj ((Cell *) o1.rec.s); switch (o1.type) { case STRING_CONSTANT: ret = o1.rec.s; break; case STRING: ret = o1.rec.s; break; case RANGE: ret = o1.rec.s; break; } return ret; } static char retbuf[32]; char * obj2text (o) obj o; { char *ret = NULL; obj o1 = obj2val (o); switch (o1.type) { case STRING_CONSTANT: ret = o1.rec.s; break; case STRING: ret = o1.rec.s; break; case INTEGER: { sprintf (retbuf, "%d", o1.rec.i); ret = retbuf; break; }; case DOUBLE: { sprintf (retbuf, "%f", o1.rec.d); ret = retbuf; break; }; } return ret; } static obj withobj[20]; static int nwith = -1; int withenter (baseobj) obj baseobj; { nwith++; withobj[nwith] = baseobj; return nwith; } int withend () { nwith--; return nwith; } obj check_with (o2) obj o2; { if (nwith >= 0) { obj o1 = withobj[nwith]; obj *base; obj *uper, *current; int i, class, member; if (o1.type == IDENTIFIER) { o1 = id2val (o1); } i = 0; class = -1; member = -1; while (o1.label != NULL && arrayclass[i].name != NULL && class < 0) { if (strcasecmp (o1.label, arrayclass[i].name) == 0) { class = i; } i++; } if (class >= 0 && member >= 0) { if (arrayclass[class].data[member].type < NUMBER_OF_CLASS) { obj arg[1]; arg[0] = o1; o2 = (arrayclass[class].data[member].getfct) (1, arg); return o2; } } base = (obj *) absmalloc (sizeof (obj), "mkderef:base"); base->type = o1.type; base->label = o1.label; base->rec.s = o1.rec.s; i = nwith - 1; current = base; while (i >= 0) { uper = (obj *) malloc (sizeof (obj)); o1 = withobj[i]; if (o1.type == IDENTIFIER) { uper = (obj *) o1.rec.s; if (uper->type == VARIANT) uper = (obj *) uper->rec.s; } else { uper->type = o1.type; uper->label = o1.label; uper->rec.s = o1.rec.s; } current->type = MEMBER; current->rec.s = (char *) uper; current = uper; i--; } o2.type = MEMBER; o2.rec.s = (char *) base; } return o2; } int freenocstobj (obj o) { o = id2val (o); switch (o.type) { case STRING: { if (o.rec.s != NULL) absfree (o.rec.s, "freenocstobj:o.rec.s STRING"); o.rec.s = NULL; break; } case RANGEN: { Range *ran = (Range *) o.rec.s; freerange (ran); break; } case MEMBER: { if (o.rec.s != NULL) { freenocstobj (*((obj *) o.rec.s)); absfree (o.rec.s, "freenocstobj:o.rec.s MEMBER"); o.rec.s = NULL; } } } return 0; } int freeobj (obj o) { switch (o.type) { case STRING_CONSTANT: { if (o.rec.s != NULL) absfree (o.rec.s, "freeobj:o.rec.s STRING_CONSTANT"); o.rec.s = NULL; break; } case MEMBER: { if (o.rec.s != NULL) { freeobj (*((obj *) o.rec.s)); absfree (o.rec.s, "freeobj:o.rec.s MEMBER"); o.rec.s = NULL; } } } return 0; } obj mkderef (o1, o2) obj o1, o2; { obj *base; obj *uper; int i, class, member; if (o1.type == IDENTIFIER) { o1 = id2val (o1); } i = 0; class = -1; while (o1.label != NULL && arrayclass[i].name != NULL && class < 0) { if (strcasecmp (o1.label, arrayclass[i].name) == 0) { class = i; } i++; } if (class >= 0) { i = 0; member = -1; while (o2.label != NULL && arrayclass[class].data[i].name != NULL && member < 0) { if (strcasecmp (o2.label, arrayclass[class].data[i].name) == 0) { member = i; } i++; } } if (class >= 0 && member >= 0) { if (arrayclass[class].data[member].type < NUMBER_OF_CLASS) { obj arg[1]; arg[0] = o1; o2 = (arrayclass[class].data[member].getfct) (1, arg); return o2; } } base = (obj *) absmalloc (sizeof (obj), "mkderef:base"); base->type = o1.type; base->label = o1.label; base->rec.s = o1.rec.s; uper = &o2; while ((uper->type == MEMBER) && uper->rec.s != NULL) { uper = (obj *) uper->rec.s; } uper->rec.s = (char *) base; return o2; } int o1eqo2 (obj * o1, obj o2) { Idval *idval; obj *val; idval = (Idval *) o1->rec.s; val = &(idval->val); if (idval->protect) return -1; switch (val->type) { case VARIANT: { val = (obj *) val->rec.s; val->rec = o2.rec; val->type = o2.type; break; } case INTEGER: val->rec.i = obj2int (o2); break; case DOUBLE: val->rec.d = obj2double (o2); break; default: { if (o2.type == STRING) { val->rec.s = absmalloc (sizeof (char) * (1 + strlen (o2.rec.s)), "mkassign::o->rec.s"); strcpy (o1->rec.s, o2.rec.s); val->type = STRING; } else { val->rec.s = o2.rec.s; val->type = o2.type; val->label = o2.label; } break; } } return 0; } int o1plusplus (obj * o1) { Idval *idval = (Idval *) o1->rec.s; obj *val = &(idval->val); if (idval->protect) return -1; if (val->type == VARIANT) val = (obj *) val->rec.s; switch (val->type) { case INTEGER: val->rec.i += 1; break; case DOUBLE: val->rec.d += 1.0; break; default: { break; } } return 0; } int o1moinsmoins (obj * o1) { Idval *idval = (Idval *) o1->rec.s; obj *val = &(idval->val); if (idval->protect) return -1; if (val->type == VARIANT) val = (obj *) val->rec.s; switch (val->type) { case INTEGER: val->rec.i -= 1; break; case DOUBLE: val->rec.d -= 1.0; break; default: { break; } } return 0; } int printobj (obj o) { if (o.type == IDENTIFIER || o.type == CONST || o.type == CONSTCONST) { fprintf (stderr, "IDENTIFIER %s : ", o.label); if (o.rec.s == NULL) { fprintf (stderr, "not allocated\n"); return 0; } else o = id2val (o); } if (o.type == DEREFID) { fprintf (stderr, "DEREFID %s : ", o.label); o = *((obj *) o.rec.s); } switch (o.type) { case STRING_CONSTANT: fprintf (stderr, "STRING_CONSTANT val %s\n", o.rec.s); break; case STRING: fprintf (stderr, "STRING val %s\n", o.rec.s); break; case INTEGER: fprintf (stderr, "INTEGER val %d\n", o.rec.i); break; case DOUBLE: fprintf (stderr, "DOUBLE val %f\n", o.rec.d); break; case CELL: fprintf (stderr, "%s type CELL \n", o.label); break; case WORKSHEET: fprintf (stderr, "%s type WORKSHEET \n", o.label); break; case MEMBER: { fprintf (stderr, "%s MEMBER of: ", o.label); if (o.rec.s != NULL) printobj (*((obj *) o.rec.s)); else printf ("\n"); break; } case OPERATION: fprintf (stderr, "operation %s %d\n", o.label, o.rec.i); break; default: { fprintf (stderr, "type %d \n", o.type); } } return 0; } int niceprintobj (o) obj o; { if (o.type == IDENTIFIER || o.type == CONST || o.type == CONSTCONST) { if (o.rec.s == NULL) { fprintf (stderr, "not allocated\n"); return 0; } o = id2val (o); } if (o.type == DEREFID) { o = *((obj *) o.rec.s); } switch (o.type) { case STRING_CONSTANT: printf ("%s ", o.rec.s); break; case STRING: printf ("%s ", o.rec.s); break; case INTEGER: printf ("%d ", o.rec.i); break; case DOUBLE: printf ("%f ", o.rec.d); break; case MEMBER: { fprintf (stderr, "%s MEMBER of: ", o.label); if (o.rec.s != NULL) printobj (*((obj *) o.rec.s)); break; } } return 0; } int getbaseclass (o2) obj o2; { int i = 0; obj *o; if (o2.type != MEMBER) return -1; o = (obj *) o2.rec.s; if (o->type != MEMBER) { return o->type; } else { while (o->label != NULL && arrayclass[i].name != NULL) { if (strcasecmp (o->label, arrayclass[i].name) == 0) { return i; } i++; } } fprintf (stderr, "objet type %s not found \n", o->label); return -1; } int getmemberpos (class, o2) int class; obj o2; { int i = 0; obj *o; if (class < NUMBER_OF_CLASS && class > 0) while (o2.label != NULL && arrayclass[class].data[i].name != NULL) { if (strcasecmp (o2.label, arrayclass[class].data[i].name) == 0) return i; i++; } o = (obj *) o2.rec.s; fprintf (stderr, "class %d, member %s not found (member of %s) !\n", class, o2.label, o->label); return -1; } obj member2val (o2) obj o2; { obj oarg[2]; int member; int class = getbaseclass (o2); if (class < 0 || class > NUMBER_OF_CLASS) return o2; member = getmemberpos (class, o2); if (member < 0) return o2; oarg[0] = o2; return (arrayclass[class].data[member].getfct) (1, oarg); } obj class2obj (o2) obj o2; { obj oarg[2]; int member; int class = o2.type; if (class < 0 || class >= NUMBER_OF_CLASS) return o2; member = 0; if (member < 0) return o2; oarg[0] = o2; return (arrayclass[class].data[0].getfct) (1, oarg); } int classname2classpos (char *name) { int i = 0; while (name != NULL && arrayclass[i].name != NULL) { if (strcasecmp (name, arrayclass[i].name) == 0) return i; i++; } return -1; } int name2type (char *name) { return classname2classpos (name); } int mkclassassign (obj o1, obj o2) { int class = o1.type; int i = 0; if (class < 0 || class >= NUMBER_OF_CLASS) return -1; while (arrayclass[class].fct[i].name != NULL) { if (!strcmp (arrayclass[class].fct[i].name, "=")) { obj args[2]; args[0] = o1; args[1] = o2; arrayclass[class].fct[i].fct (2, args); return 0; } i++; } return 0; } int objcmp (obj o1, obj o2) { o1 = obj2val (o1); o2 = obj2val (o2); if (o1.type == o2.type) switch (o1.type) { case STRING_CONSTANT: return !(strcmp (o1.rec.s, o2.rec.s)); case INTEGER: return (o1.rec.i == o2.rec.i); case DOUBLE: return (o1.rec.d == o2.rec.d); } return (obj2double (o1) == obj2double (o2)); }