Commit 3e1ad0b1 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

add handlers for binary/unary ops, cellrefs, and constants. Still needs


2002-07-12  Jody Goldberg <jody@gnome.org>

	* qpro-read.c (qpro_parse_formula) : add handlers for binary/unary ops,
	  cellrefs, and constants.  Still needs work for rangerefs,
	  and functions.  Could also use some testing for abs/rel and sheet
	  qualified references.
parent d79df619
2002-07-12 Jody Goldberg <jody@gnome.org>
* qpro-read.c (qpro_parse_formula) : add handlers for binary/unary ops,
cellrefs, and constants. Still needs work for rangerefs,
and functions. Could also use some testing for abs/rel and sheet
qualified references.
2002-07-12 Jody Goldberg <jody@gnome.org>
* qpro-read.c (qpro_parse_formula) : make a guess about string and
error states.
2002-07-12 Jody Goldberg <jody@gnome.org>
* qpro-read.c : Ok we do a few things now.
......
......@@ -30,6 +30,7 @@
#include <sheet.h>
#include <cell.h>
#include <value.h>
#include <expr.h>
#include <sheet-style.h>
#include <style-color.h>
#include <parse-util.h>
......@@ -102,7 +103,9 @@ qpro_get_record (QProReadState *state, guint16 *id, guint16 *len)
*id = GSF_LE_GET_GUINT16 (data + 0);
*len = GSF_LE_GET_GUINT16 (data + 2);
#if 0
printf ("%hd with %hd\n", *id, *len);
#endif
if (*len == 0)
return "";
......@@ -110,7 +113,7 @@ qpro_get_record (QProReadState *state, guint16 *id, guint16 *len)
g_return_val_if_fail (*len < 0x2000, NULL);
data = gsf_input_read (state->input, *len, NULL);
if (data == NULL)
g_warning ("huh? failue reading %hd for type %hd", *len, *id);
g_warning ("huh? failure reading %hd for type %hd", *len, *id);
return data;
}
......@@ -131,18 +134,175 @@ qpro_validate_len (QProReadState *state, char const *id, guint16 len, int expect
return TRUE;
}
static void
qpro_parse_formula (QProReadState *state, int col, int row,
guint8 const *data)
guint8 const *data, guint8 const *end)
{
double val = gnumeric_get_le_double (data);
int ex;
frexp (val, &ex);
int magic = GSF_LE_GET_GUINT16 (data + 6) & 0x7ff8;
guint16 ref_offset = GSF_LE_GET_GUINT16 (data + 12);
Value *val;
GSList *stack = NULL;
GnmExpr const *expr;
guint8 const *refs, *fmla;
int len;
fmla = data + 14;
refs = fmla + ref_offset;
g_return_if_fail (refs <= end);
#if 0
puts (cell_coord_name (col, row));
printf ("Exp = 0x%x, %g %d\n", (GSF_LE_GET_GUINT16 (data + 6) >> 1) & 0x7ff,
val, ex);
gsf_mem_dump (data, 8);
gsf_mem_dump (fmla, refs-fmla);
gsf_mem_dump (refs, end-fmla);
#endif
while (fmla < refs && *fmla != QPRO_OP_EOF) {
expr = NULL;
len = 1;
switch (*fmla) {
case QPRO_OP_CONST_FLOAT:
expr = gnm_expr_new_constant (value_new_float (
gnumeric_get_le_double (fmla+1)));
len = 9;
break;
case QPRO_OP_CELLREF: {
CellRef ref;
guint16 tmp = GSF_LE_GET_GUINT16 (refs + 4);
ref.sheet = NULL;
ref.col = *((gint8 *)(refs + 2));
ref.col_relative = (tmp & 0x4000) ? TRUE : FALSE;
ref.row_relative = (tmp & 0x2000) ? TRUE : FALSE;
if (ref.row_relative)
ref.row = ((gint16)(tmp & 0x1fff) << 3) >> 3;
else
ref.row = tmp & 0x1fff;
expr = gnm_expr_new_cellref (&ref);
refs += 6;
break;
}
case QPRO_OP_RANGEREF: {
CellRef a, b;
expr = gnm_expr_new_constant (
value_new_cellrange_unsafe (&a, &b));
refs += 10;
break;
}
case QPRO_OP_EOF: break; /* exit */
case QPRO_OP_PAREN: break; /* ignore for now */
case QPRO_OP_CONST_INT:
expr = gnm_expr_new_constant (
value_new_int ((gint16)GSF_LE_GET_GUINT16 (fmla+1)));
len = 3;
break;
case QPRO_OP_CONST_STR:
expr = gnm_expr_new_constant (value_new_string (fmla+1));
len = 1 + strlen (fmla+1) + 1;
break;
case QPRO_OP_DEFAULT_ARG:
expr = gnm_expr_new_constant (value_new_empty ());
break;
case QPRO_OP_ADD: case QPRO_OP_SUB:
case QPRO_OP_MULT: case QPRO_OP_DIV:
case QPRO_OP_EXP:
case QPRO_OP_EQ: case QPRO_OP_NE:
case QPRO_OP_LE: case QPRO_OP_GE:
case QPRO_OP_LT: case QPRO_OP_GT:
case QPRO_OP_CONCAT: {
static GnmExprOp const binop_map[] = {
GNM_EXPR_OP_ADD, GNM_EXPR_OP_SUB,
GNM_EXPR_OP_MULT, GNM_EXPR_OP_DIV,
GNM_EXPR_OP_EXP,
GNM_EXPR_OP_EQUAL, GNM_EXPR_OP_NOT_EQUAL,
GNM_EXPR_OP_LTE, GNM_EXPR_OP_GTE,
GNM_EXPR_OP_LT, GNM_EXPR_OP_GT,
0, 0, 0, 0,
GNM_EXPR_OP_CAT
};
GnmExpr const *l, *r;
GSList *tmp = stack;
g_return_if_fail (stack != NULL && stack->next != NULL);
r = stack->data;
l = stack->next->data;
stack = stack->next->next;
tmp->next->next = NULL;
g_slist_free (tmp);
expr = gnm_expr_new_binary (
l, binop_map [*fmla - QPRO_OP_ADD], r);
break;
}
case QPRO_OP_AND:
case QPRO_OP_OR:
case QPRO_OP_NOT:
case QPRO_OP_UNARY_NEG:
case QPRO_OP_UNARY_PLUS: {
GSList *tmp = stack;
g_return_if_fail (stack != NULL);
expr = stack->data;
stack = stack->next;
tmp->next= NULL;
g_slist_free (tmp);
expr = gnm_expr_new_unary ((*fmla == QPRO_OP_UNARY_NEG)
? GNM_EXPR_OP_UNARY_NEG : GNM_EXPR_OP_UNARY_PLUS,
expr);
break;
}
default:
if (QPRO_OP_FIRST_FUNC <= *fmla && *fmla <= QPRO_OP_LAST_FUNC) {
}
}
if (expr != NULL) {
stack = g_slist_prepend (stack, (gpointer)expr);
}
fmla += len;
}
g_return_if_fail (fmla != refs);
g_return_if_fail (stack != NULL);
g_return_if_fail (stack->next == NULL);
expr = stack->data;
g_slist_free (stack);
if (magic == 0x7ff0) {
val = value_new_error (NULL, gnumeric_err_VALUE);
} else if (magic == 0x7ff8) {
guint16 id, len;
int new_row, new_col;
data = qpro_get_record (state, &id, &len);
g_return_if_fail (data != NULL);
g_return_if_fail (id == QPRO_FORMULA_STRING);
new_col = data [0];
new_row = GSF_LE_GET_GUINT16 (data + 2);
/* Be anal */
g_return_if_fail (col == new_col);
g_return_if_fail (row == new_row);
val = value_new_string (data + 7);
} else
val = value_new_float (gnumeric_get_le_double (data));
cell_set_expr_and_value (sheet_cell_fetch (state->cur_sheet, col, row),
expr, val, TRUE);
gnm_expr_unref (expr);
}
static MStyle *
......@@ -215,7 +375,8 @@ qpro_read_sheet (QProReadState *state)
sheet_style_set_pos (sheet, col, row,
qpro_get_style (state, data + 4));
qpro_parse_formula (state, col, row, data + 6);
qpro_parse_formula (state, col, row,
data + 6, data + len);
}
break;
......
......@@ -184,6 +184,169 @@ typedef enum {
QPRO_LAST_SANE_ID = 1999,
QPRO_UNKNOWN = 0xdead,
} qpro_record_t;
} QProRecord;
typedef enum {
QPRO_OP_CONST_FLOAT = 0,
QPRO_OP_CELLREF = 1,
QPRO_OP_RANGEREF = 2,
QPRO_OP_EOF = 3, /* End of Formula */
QPRO_OP_PAREN = 4, /* Parenthesis */
QPRO_OP_CONST_INT = 5,
QPRO_OP_CONST_STR = 6,
QPRO_OP_DEFAULT_ARG = 7, /* Default argument, assumed to be 0 */
QPRO_OP_UNARY_NEG = 8,
QPRO_OP_ADD = 9,
QPRO_OP_SUB = 10,
QPRO_OP_MULT = 11,
QPRO_OP_DIV = 12,
QPRO_OP_EXP = 13,
QPRO_OP_EQ = 14,
QPRO_OP_NE = 15,
QPRO_OP_LE = 16,
QPRO_OP_GE = 17,
QPRO_OP_LT = 18,
QPRO_OP_GT = 19,
QPRO_OP_AND = 20,
QPRO_OP_OR = 21,
QPRO_OP_NOT = 22,
QPRO_OP_UNARY_PLUS = 23,
QPRO_OP_CONCAT = 24,
#if 0
/* What do these do */
QPRO_OP_ = 25, /* Halt */
QPRO_OP_ = 26, /* DLL Function */
QPRO_OP_ = 27, /* Extended No Operands */
QPRO_OP_ = 28, /* Extended Operands */
QPRO_OP_ = 29, /* Reserved */
QPRO_OP_ = 30, /* Reserved */
#endif
QPRO_OP_FUNC_NA = 31, /* NA */
QPRO_OP_FIRST_FUNC = 32,
QPRO_OP_FUNC_ERR = 32, /* @Err */
QPRO_OP_FUNC_ABS = 33, /* @Abs */
QPRO_OP_FUNC_INT = 34, /* @Int */
QPRO_OP_FUNC_SQRT = 35, /* @Sqrt */
QPRO_OP_FUNC_LOG = 36, /* @Log */
QPRO_OP_FUNC_LN = 37, /* @Ln */
QPRO_OP_FUNC_PI = 38, /* @Pi */
QPRO_OP_FUNC_SIN = 39, /* @Sin */
QPRO_OP_FUNC_COS = 40, /* @Cos */
QPRO_OP_FUNC_TAN = 41, /* @Tan */
QPRO_OP_FUNC_ATAN2 = 42, /* @Atan2 */
QPRO_OP_FUNC_ATAN = 43, /* @Atan */
QPRO_OP_FUNC_ASIN = 44, /* @Asin */
QPRO_OP_FUNC_ACOS = 45, /* @Acos */
QPRO_OP_FUNC_EXP = 46, /* @Exp */
QPRO_OP_FUNC_MOD = 47, /* @Mod */
QPRO_OP_FUNC_CHOOSE = 48, /* @Choose */
QPRO_OP_FUNC_ISNA = 49, /* @Isna */
QPRO_OP_FUNC_ISERR = 50, /* @Iserr */
QPRO_OP_FUNC_FALSE = 51, /* @False */
QPRO_OP_FUNC_TRUE = 52, /* @True */
QPRO_OP_FUNC_RAND = 53, /* @Rand */
QPRO_OP_FUNC_DATE = 54, /* @Date */
QPRO_OP_FUNC_NOW = 55, /* @Now */
QPRO_OP_FUNC_PMT = 56, /* @Pmt */
QPRO_OP_FUNC_PV = 57, /* @Pv */
QPRO_OP_FUNC_FV = 58, /* @Fv */
QPRO_OP_FUNC_IF = 59, /* @If */
QPRO_OP_FUNC_DAY = 60, /* @Day */
QPRO_OP_FUNC_MONTH = 61, /* @Month */
QPRO_OP_FUNC_YEAR = 62, /* @Year */
QPRO_OP_FUNC_ROUND = 63, /* @Round */
QPRO_OP_FUNC_TIME = 64, /* @Time */
QPRO_OP_FUNC_HOUR = 65, /* @Hour */
QPRO_OP_FUNC_MINUTE = 66, /* @Minute */
QPRO_OP_FUNC_SECOND = 67, /* @Second */
QPRO_OP_FUNC_ISNUM = 68, /* @Isnum */
QPRO_OP_FUNC_ISSTR = 69, /* @Isstr */
QPRO_OP_FUNC_LENGTH = 70, /* @Length */
QPRO_OP_FUNC_VALUE = 71, /* @Value */
QPRO_OP_FUNC_STRING = 72, /* @String */
QPRO_OP_FUNC_MID = 73, /* @Mid */
QPRO_OP_FUNC_CHAR = 74, /* @Char */
QPRO_OP_FUNC_CODE = 75, /* @Code */
QPRO_OP_FUNC_FIND = 76, /* @Find */
QPRO_OP_FUNC_DATEVAL = 77, /* @DateVal */
QPRO_OP_FUNC_TIMEVAL = 78, /* @TimeVal */
QPRO_OP_FUNC_CELLPTR = 79, /* @CellPtr */
QPRO_OP_FUNC_SUM = 80, /* @Sum */
QPRO_OP_FUNC_AVG = 81, /* @Avg */
QPRO_OP_FUNC_COUNT = 82, /* @Count */
QPRO_OP_FUNC_MIN = 83, /* @Min */
QPRO_OP_FUNC_MAX = 84, /* @Max */
QPRO_OP_FUNC_VLOOKUP = 85, /* @Vlookup */
QPRO_OP_FUNC_NPV1 = 86, /* @Npv */
QPRO_OP_FUNC_VAR = 87, /* @Var */
QPRO_OP_FUNC_STD = 88, /* @Std */
QPRO_OP_FUNC_IRR = 89, /* @Irr */
QPRO_OP_FUNC_HLOOKUP = 90, /* @Hlookup */
QPRO_OP_FUNC_DSUM = 91, /* @Dsum */
QPRO_OP_FUNC_DAVG = 92, /* @Davg */
QPRO_OP_FUNC_DCOUNT = 93, /* @Dcount */
QPRO_OP_FUNC_DMIN = 94, /* @Dmin */
QPRO_OP_FUNC_DMAX = 95, /* @Dmax */
QPRO_OP_FUNC_DVAR = 96, /* @Dvar */
QPRO_OP_FUNC_DSTD = 97, /* @Dstd */
QPRO_OP_FUNC_INDEX2D = 98, /* @Index2d */
QPRO_OP_FUNC_COLS = 99, /* @Cols */
QPRO_OP_FUNC_ROWS = 100, /* @Rows */
QPRO_OP_FUNC_REPEAT = 101, /* @Repeat */
QPRO_OP_FUNC_UPPER = 102, /* @Upper */
QPRO_OP_FUNC_LOWER = 103, /* @Lower */
QPRO_OP_FUNC_LEFT = 104, /* @Left */
QPRO_OP_FUNC_RIGHT = 105, /* @Right */
QPRO_OP_FUNC_REPLACE = 106, /* @Replace */
QPRO_OP_FUNC_PROPER = 107, /* @Proper */
QPRO_OP_FUNC_CELL = 108, /* @Cell */
QPRO_OP_FUNC_TRIM = 109, /* @Trim */
QPRO_OP_FUNC_CLEAN = 110, /* @Clean */
QPRO_OP_FUNC_S = 111, /* @S */
QPRO_OP_FUNC_N = 112, /* @N */
QPRO_OP_FUNC_EXACT = 113, /* @Exact */
QPRO_OP_FUNC_CALL = 114, /* @Call */
QPRO_OP_FUNC_@ = 115, /* @@ */
QPRO_OP_FUNC_RATE = 116, /* @Rate */
QPRO_OP_FUNC_TERM = 117, /* @Term */
QPRO_OP_FUNC_CTERM = 118, /* @Cterm */
QPRO_OP_FUNC_SLN = 119, /* @Sln */
QPRO_OP_FUNC_SYD = 120, /* @Syd */
QPRO_OP_FUNC_DDB = 121, /* @Ddb */
QPRO_OP_FUNC_STDS = 122, /* @Stds */
QPRO_OP_FUNC_VARS = 123, /* @Vars */
QPRO_OP_FUNC_DSTDS = 124, /* @Dstds */
QPRO_OP_FUNC_DVARS = 125, /* @Dvars */
QPRO_OP_FUNC_PVAL = 126, /* @Pval */
QPRO_OP_FUNC_PAYMT = 127, /* @Paymt */
QPRO_OP_FUNC_FVAL = 128, /* @Fval */
QPRO_OP_FUNC_NPER = 129, /* @Nper */
QPRO_OP_FUNC_IRATE = 130, /* @Irate */
QPRO_OP_FUNC_IPAYMT = 131, /* @Ipaymt */
QPRO_OP_FUNC_PPAYMT = 132, /* @Ppaymt */
QPRO_OP_FUNC_SUMPRODUCT = 133, /* @SumProduct */
QPRO_OP_FUNC_MEMAVAIL = 134, /* @MemAvail */
QPRO_OP_FUNC_MEMEMSAVAIL = 135, /* @MemEmsAvail */
QPRO_OP_FUNC_FILEEXISTS = 136, /* @FileExists */
QPRO_OP_FUNC_CURVALUE = 137, /* @CurValue */
QPRO_OP_FUNC_DEGREES = 138, /* @Degrees */
QPRO_OP_FUNC_RADIANS = 139, /* @Radians */
QPRO_OP_FUNC_HEXTONUM = 140, /* @HexToNum */
QPRO_OP_FUNC_NUMTOHEX = 141, /* @NumToHex */
QPRO_OP_FUNC_TODAY = 142, /* @Today */
QPRO_OP_FUNC_NPV2 = 143, /* @Npv */
QPRO_OP_FUNC_CELLINDEX2D = 144, /* @CellIndex2d */
QPRO_OP_FUNC_VERSION = 145, /* @Version */
QPRO_OP_FUNC_SHEETS = 154, /* @Sheets */
QPRO_OP_FUNC_INDEX3D = 157, /* @Index3d */
QPRO_OP_FUNC_CELLINDEX3D = 158, /* @CellIndex3d */
QPRO_OP_FUNC_PROPERTY = 159, /* @Property */
QPRO_OP_FUNC_DDELINK = 160, /* @DDELink */
QPRO_OP_FUNC_COMMAND = 161, /* @Command */
QPRO_OP_LAST_FUNC = 161,
} QProOperators;
#endif /* __QPRO_H__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment