home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
-
- This file is part of Oleo, the GNU Spreadsheet.
-
- Oleo 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, or (at your option)
- any later version.
-
- Oleo 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 Oleo; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #define obstack_chunk_alloc ck_malloc
- #define obstack_chunk_free free
- #include "obstack.h"
- #include "funcdef.h"
- #include "sysdef.h"
-
- #include "global.h"
- #include "cell.h"
- #include "eval.h"
- #include "errors.h"
- #include "lists.h"
- #include "format.h"
- #include "io-abstract.h"
- #include "io-generic.h"
- #include "io-term.h"
- #include "cmd.h"
-
- struct value
- {
- int type;
- union vals x;
- };
-
- #define Float x.c_d
- #define String x.c_s
- #define Int x.c_l
- #define Value x.c_i
- #define Rng x.c_r
-
- #define ERROR(x) \
- { \
- p->Value=x; \
- p->type=TYP_ERR;\
- return; \
- }
-
-
- static int
- cell (row, col, dowhat, p)
- long row;
- long col;
- char *dowhat;
- struct value *p;
- {
- struct func
- {
- char *name;
- int typ;
- };
-
- static struct func cell_funs[] =
- {
- {"row", TYP_INT},
- {"column", TYP_INT},
- {"width", TYP_INT},
- {"lock", TYP_STR},
- {"protection", TYP_STR},
- {"justify", TYP_STR},
- {"alignment", TYP_STR},
- {"fmt", TYP_STR},
- {"format", TYP_STR},
- {"type", TYP_STR},
- {"formula", TYP_STR},
- {"value", 0},
- {0, 0}
- };
-
- CELL *cell_ptr;
- char *strptr;
- struct func *func;
- struct func *f1;
- int n;
-
- n = strlen (dowhat) - 1;
- f1 = 0;
- for (func = cell_funs; func->name; func++)
- if (func->name[0] == dowhat[0]
- && (n == 0 || !strincmp (&(func->name[1]), &dowhat[1], n)))
- {
- if (f1)
- return BAD_INPUT;
- f1 = func;
- }
- if (!f1)
- return BAD_INPUT;
- p->type = f1->typ;
- switch (f1 - cell_funs)
- {
- case 0:
- p->Int = row;
- break;
- case 1:
- p->Int = col;
- break;
- case 2:
- p->Int = get_width (col);
- break;
- case 3:
- case 4:
- cell_ptr = find_cell (row, col);
- p->String = ( (cell_ptr ? GET_LCK (cell_ptr) : default_lock)
- ? "locked"
- : "unlocked");
- break;
- case 5:
- case 6:
- cell_ptr = find_cell (row, col);
- p->String = jst_to_str (cell_ptr ? GET_JST (cell_ptr) : default_jst);
- break;
- case 7:
- case 8:
- p->String = fmt_to_str ((cell_ptr = find_cell (row, col)) ? GET_FMT (cell_ptr) : 0);
- break;
- case 9:
- cell_ptr = find_cell (row, col);
- if (cell_ptr)
- switch (GET_TYP (cell_ptr))
- {
- case TYP_FLT:
- p->String = "float";
- break;
- case TYP_INT:
- p->String = "integer";
- break;
- case TYP_STR:
- p->String = "string";
- break;
- case TYP_BOL:
- p->String = "boolean";
- break;
- case TYP_ERR:
- p->String = "error";
- break;
- default:
- p->String = "unknown";
- }
- else
- p->String = "null";
- break;
- case 10:
- cell_ptr = find_cell (row, col);
- if (cell_ptr && (GET_TYP (cell_ptr) || cell_ptr->cell_formula))
- {
- strptr = decomp (row, col, cell_ptr);
- p->String = obstack_alloc (&tmp_mem, strlen (strptr) + 1);
- strcpy (p->String, strptr);
- decomp_free ();
- }
- else
- p->String = "";
- break;
- case 11:
- cell_ptr = find_cell (row, col);
- if (cell_ptr)
- {
- p->type = GET_TYP (cell_ptr);
- p->x = cell_ptr->c_z;
- }
- else
- p->type = 0;
- break;
- default:
- return BAD_INPUT;
- }
- return 0;
- }
-
-
- static void
- do_curcell (p)
- struct value *p;
- {
- int tmp;
-
- tmp = cell (curow, cucol, p->String, p);
- if (tmp)
- ERROR (tmp);
- }
-
- static void
- do_my (p)
- struct value *p;
- {
- int tmp;
-
- tmp = cell (cur_row, cur_col, p->String, p);
- if (tmp)
- ERROR (tmp);
- }
-
- /* Note that the second argument may be *anything* including ERROR. If it is
- error, we find the first occurence of that ERROR in the range */
-
- static void
- do_member (p)
- struct value *p;
- {
- CELLREF crow;
- CELLREF ccol;
- int foundit;
- CELL *cell_ptr;
-
- find_cells_in_range (&(p->Rng));
- while (cell_ptr = next_row_col_in_range (&crow, &ccol))
- {
- if (GET_TYP (cell_ptr) != (p + 1)->type)
- continue;
- switch ((p + 1)->type)
- {
- case 0:
- foundit = 1;
- break;
- case TYP_FLT:
- foundit = cell_ptr->cell_flt == (p + 1)->Float;
- break;
- case TYP_INT:
- foundit = cell_ptr->cell_int == (p + 1)->Int;
- break;
- case TYP_STR:
- foundit = !strcmp (cell_ptr->cell_str, (p + 1)->String);
- break;
- case TYP_BOL:
- foundit = cell_ptr->cell_bol == (p + 1)->Value;
- break;
- case TYP_ERR:
- foundit = cell_ptr->cell_err == (p + 1)->Value;
- break;
- default:
- foundit = 0;
- #ifdef TEST
- panic ("Unknown type (%d) in member", (p + 1)->type);
- #endif
- }
- if (foundit)
- {
- no_more_cells ();
- p->Int = 1 + crow - p->Rng.lr + (ccol - p->Rng.lc) * (1 + p->Rng.hr - p->Rng.lr);
- p->type = TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type = TYP_INT;
- }
-
- static void
- do_smember (p)
- struct value *p;
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- char *string;
-
- string = (p + 1)->String;
- find_cells_in_range (&(p->Rng));
- while (cell_ptr = next_row_col_in_range (&crow, &ccol))
- {
- if (((GET_TYP (cell_ptr) == 0) && (string[0] == '\0'))
- || (cell_ptr && (GET_TYP (cell_ptr) == TYP_STR)
- && strstr (string, cell_ptr->cell_str)))
- {
- no_more_cells ();
- p->Int = 1 + (crow - p->Rng.lr)
- + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
- p->type = TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type = TYP_INT;
- }
-
- static void
- do_members (p)
- struct value *p;
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- char *string;
-
- string = (p + 1)->String;
- find_cells_in_range (&(p->Rng));
- while (cell_ptr = next_row_col_in_range (&crow, &ccol))
- {
- if (GET_TYP (cell_ptr) != TYP_STR)
- continue;
- if (strstr (cell_ptr->cell_str, string))
- {
- no_more_cells ();
- p->Int = 1 + (crow - p->Rng.lr)
- + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
- p->type = TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type = TYP_INT;
- }
-
- static void
- do_pmember (p)
- struct value *p;
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- char *string;
-
- string = (p + 1)->String;
- find_cells_in_range (&(p->Rng));
- while (cell_ptr = next_row_col_in_range (&crow, &ccol))
- {
- if ((GET_TYP (cell_ptr) == 0 && string[0] == '\0')
- || (cell_ptr && GET_TYP (cell_ptr) == TYP_STR && !strncmp (string, cell_ptr->cell_str, strlen (cell_ptr->cell_str))))
- {
- no_more_cells ();
- p->Int = 1 + (crow - p->Rng.lr)
- + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
- p->type = TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type = TYP_INT;
- }
-
- static void
- do_memberp (p)
- struct value *p;
- {
- CELLREF crow;
- CELLREF ccol;
- CELL *cell_ptr;
- int tmp;
- char *string;
-
- string = (p + 1)->String;
- find_cells_in_range (&(p->Rng));
- tmp = strlen (string);
- while (cell_ptr = next_row_col_in_range (&crow, &ccol))
- {
- if (GET_TYP (cell_ptr) != TYP_STR)
- continue;
- if (!strncmp (cell_ptr->cell_str, string, tmp))
- {
- no_more_cells ();
- p->Int = 1 + (crow - p->Rng.lr)
- + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
- p->type = TYP_INT;
- return;
- }
- }
- p->Int = 0L;
- p->type = TYP_INT;
- }
-
- static void
- do_hlookup (p)
- struct value *p;
- {
-
- struct rng *rng = &((p)->Rng);
- double fltval = (p + 1)->Float;
- long offset = (p + 2)->Int;
-
- CELL *cell_ptr;
- double f;
- CELLREF col;
- CELLREF row;
- char *strptr;
-
- row = rng->lr;
- for (col = rng->lc; col <= rng->hc; col++)
- {
- if (!(cell_ptr = find_cell (row, col)))
- ERROR (NON_NUMBER);
- switch (GET_TYP (cell_ptr))
- {
- case TYP_FLT:
- if (fltval < cell_ptr->cell_flt)
- goto out;
- break;
- case TYP_INT:
- if (fltval < cell_ptr->cell_int)
- goto out;
- break;
- case TYP_STR:
- strptr = cell_ptr->cell_str;
- f = astof (&strptr);
- if (!*strptr && fltval > f)
- goto out;
- else
- ERROR (NON_NUMBER);
- case 0:
- case TYP_BOL:
- case TYP_ERR:
- default:
- ERROR (NON_NUMBER);
- }
- }
- out:
- if (col == rng->lc)
- ERROR (OUT_OF_RANGE);
- --col;
- row = rng->lr + offset;
- if (row > rng->hr)
- ERROR (OUT_OF_RANGE);
- cell_ptr = find_cell (row, col);
- if (!cell_ptr)
- {
- p->type = 0;
- p->Int = 0;
- }
- else
- {
- p->type = GET_TYP (cell_ptr);
- p->x = cell_ptr->c_z;
- }
- }
-
- static void
- do_vlookup (p)
- struct value *p;
- {
-
- struct rng *rng = &((p)->Rng);
- double fltval = (p + 1)->Float;
- long offset = (p + 2)->Int;
-
- CELL *cell_ptr;
- double f;
- CELLREF col;
- CELLREF row;
- char *strptr;
-
- col = rng->lc;
- for (row = rng->lr; row <= rng->hr; row++)
- {
- if (!(cell_ptr = find_cell (row, col)))
- ERROR (NON_NUMBER);
- switch (GET_TYP (cell_ptr))
- {
- case TYP_FLT:
- if (fltval < cell_ptr->cell_flt)
- goto out;
- break;
- case TYP_INT:
- if (fltval < cell_ptr->cell_int)
- goto out;
- break;
- case TYP_STR:
- strptr = cell_ptr->cell_str;
- f = astof (&strptr);
- if (!*strptr && fltval > f)
- goto out;
- else
- ERROR (NON_NUMBER);
- case 0:
- case TYP_BOL:
- case TYP_ERR:
- default:
- ERROR (NON_NUMBER);
- }
- }
- out:
- if (row == rng->lr)
- ERROR (OUT_OF_RANGE);
- --row;
- col = rng->lc + offset;
- if (col > rng->hc)
- ERROR (OUT_OF_RANGE);
-
- cell_ptr = find_cell (row, col);
- if (!cell_ptr)
- {
- p->type = 0;
- p->Int = 0;
- }
- else
- {
- p->type = GET_TYP (cell_ptr);
- p->x = cell_ptr->c_z;
- }
- }
-
- static void
- do_vlookup_str (p)
- struct value *p;
- {
-
- struct rng *rng = &((p)->Rng);
- char * key = (p + 1)->String;
- long offset = (p + 2)->Int;
-
- CELL *cell_ptr;
- CELLREF col;
- CELLREF row;
-
- col = rng->lc;
- for (row = rng->lr; row <= rng->hr; row++)
- {
- if (!(cell_ptr = find_cell (row, col)))
- ERROR (NON_NUMBER);
- switch (GET_TYP (cell_ptr))
- {
- case TYP_STR:
- if (!strcmp (key, cell_ptr->cell_str))
- goto out;
- break;
- case 0:
- case TYP_FLT:
- case TYP_INT:
- case TYP_BOL:
- case TYP_ERR:
- default:
- ERROR (NON_NUMBER);
- }
- }
- out:
- if (row > rng->hr)
- ERROR (OUT_OF_RANGE);
- col = rng->lc + offset;
- if (col > rng->hc)
- ERROR (OUT_OF_RANGE);
-
- cell_ptr = find_cell (row, col);
- if (!cell_ptr)
- {
- p->type = 0;
- p->Int = 0;
- }
- else
- {
- p->type = GET_TYP (cell_ptr);
- p->x = cell_ptr->c_z;
- }
- }
-
-
- static void
- do_cell (p)
- struct value *p;
- {
- int tmp;
-
- tmp = cell (p->Int, (p + 1)->Int, (p + 2)->String, p);
- if (tmp)
- ERROR (tmp);
- }
-
- struct function cells_funs[] =
- {
- {C_FN1 | C_T, X_A1, "S", do_curcell, "curcell"},
- {C_FN1 | C_T, X_A1, "S", do_my, "my"},
- {C_FN3 | C_T, X_A3, "IIS", do_cell, "cell"},
-
- {C_FN2, X_A2, "RA", do_member, "member"},
- {C_FN2, X_A2, "RS", do_smember, "smember"},
- {C_FN2, X_A2, "RS", do_members, "members"},
- {C_FN2, X_A2, "RS", do_pmember, "pmember"},
- {C_FN2, X_A2, "RS", do_memberp, "memberp"},
-
- {C_FN3, X_A3, "RFI", do_hlookup, "hlookup"},
- {C_FN3, X_A3, "RFI", do_vlookup, "vlookup"},
- {C_FN3, X_A3, "RSI", do_vlookup_str, "vlookup_str"},
-
- {0, 0, "", 0, 0},
- };
-