Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GNOME
gnumeric
Commits
86c717b2
Commit
86c717b2
authored
Aug 05, 1998
by
Arturo Espinosa
Browse files
We got functions today.
We got functions today. Miguel.
parent
5908feed
Changes
11
Hide whitespace changes
Inline
Side-by-side
ChangeLog-1999-07-09
View file @
86c717b2
1998-08-04 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/func.c: More functions added.
* src/symbol.c (g_strcase_equal): Symbol hash table does is
case-insensitive.
* src/expr.c (eval_funcall): Added function evaluation.
1998-08-03 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/eval.c: New file. Move the evaluation routines here.
...
...
ChangeLog-2000-02-23
View file @
86c717b2
1998-08-04 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/func.c: More functions added.
* src/symbol.c (g_strcase_equal): Symbol hash table does is
case-insensitive.
* src/expr.c (eval_funcall): Added function evaluation.
1998-08-03 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/eval.c: New file. Move the evaluation routines here.
...
...
OChangeLog-1999-07-09
View file @
86c717b2
1998-08-04 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/func.c: More functions added.
* src/symbol.c (g_strcase_equal): Symbol hash table does is
case-insensitive.
* src/expr.c (eval_funcall): Added function evaluation.
1998-08-03 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/eval.c: New file. Move the evaluation routines here.
...
...
OChangeLog-2000-02-23
View file @
86c717b2
1998-08-04 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/func.c: More functions added.
* src/symbol.c (g_strcase_equal): Symbol hash table does is
case-insensitive.
* src/expr.c (eval_funcall): Added function evaluation.
1998-08-03 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/eval.c: New file. Move the evaluation routines here.
...
...
src/expr.c
View file @
86c717b2
...
...
@@ -140,6 +140,24 @@ value_cast_to_float (Value *v)
return
newv
;
}
float_t
value_get_as_double
(
Value
*
v
)
{
if
(
v
->
type
==
VALUE_STRING
){
return
atof
(
v
->
v
.
str
->
str
);
}
if
(
v
->
type
==
VALUE_CELLRANGE
){
g_warning
(
"Getting range as a double: what to do?"
);
return
0
.
0
;
}
if
(
v
->
type
==
VALUE_INTEGER
)
return
(
float_t
)
v
->
v
.
v_int
;
return
v
->
v
.
v_float
;
}
static
Value
*
eval_cell_value
(
Sheet
*
sheet
,
Value
*
value
)
{
...
...
@@ -171,6 +189,60 @@ eval_cell_value (Sheet *sheet, Value *value)
return
res
;
}
static
Value
*
eval_funcall
(
Sheet
*
sheet
,
ExprTree
*
tree
,
int
eval_col
,
int
eval_row
,
char
**
error_string
)
{
FunctionDefinition
*
fd
;
GList
*
l
;
int
argc
,
arg
,
i
;
Value
*
v
;
fd
=
(
FunctionDefinition
*
)
tree
->
u
.
function
.
symbol
->
data
;
l
=
tree
->
u
.
function
.
arg_list
;
argc
=
g_list_length
(
l
);
if
(
fd
->
expr_fn
)
{
/* Functions that deal with ExprNodes */
v
=
fd
->
expr_fn
(
sheet
,
l
,
eval_col
,
eval_row
,
error_string
);
}
else
{
/* Functions that take pre-computed Values */
Value
**
values
;
int
fn_argc
;
char
*
arg_type
=
fd
->
args
;
fn_argc
=
strlen
(
fd
->
args
);
if
(
fn_argc
!=
argc
){
*
error_string
=
_
(
"Invalid number of arguments"
);
return
NULL
;
}
values
=
g_new
(
Value
*
,
argc
);
for
(
arg
=
0
;
l
;
l
=
l
->
next
,
arg
++
,
arg_type
++
){
ExprTree
*
t
=
(
ExprTree
*
)
l
->
data
;
v
=
eval_expr
(
sheet
,
t
,
eval_col
,
eval_row
,
error_string
);
if
(
v
==
NULL
)
goto
free_list
;
values
[
arg
]
=
v
;
}
v
=
fd
->
fn
(
arg
+
1
,
values
,
error_string
);
free_list:
for
(
i
=
0
;
i
<
arg
;
i
++
)
value_release
(
values
[
i
]);
g_free
(
values
);
return
v
;
}
return
v
;
}
Value
*
eval_expr
(
void
*
asheet
,
ExprTree
*
tree
,
int
eval_col
,
int
eval_row
,
char
**
error_string
)
{
...
...
@@ -291,9 +363,7 @@ eval_expr (void *asheet, ExprTree *tree, int eval_col, int eval_row, char **erro
return
NULL
;
case
OP_FUNCALL
:
g_warning
(
"Function call not implemented yet
\n
"
);
*
error_string
=
_
(
"OOPS"
);
return
NULL
;
return
eval_funcall
(
sheet
,
tree
,
eval_col
,
eval_row
,
error_string
);
case
OP_CONSTANT
:
return
eval_cell_value
(
sheet
,
tree
->
u
.
constant
);
...
...
src/expr.h
View file @
86c717b2
...
...
@@ -90,6 +90,35 @@ typedef enum {
PARSE_ERR_SYNTAX
}
ParseErr
;
/*
* Functions come in two fashions: Those that only deal with
* very specific data types and a constant number of arguments,
* and those who dont.
*
* The former kind of functions receives a precomputed array of
* Value pointers.
*
* The latter sort of functions receives the plain ExprNodes and
* it is up to that routine to do the value computations and range
* processing.
*/
typedef
struct
{
/* The function name */
char
*
name
;
/* The types accepted:
* f for float
* s for string
* b for boolean
*/
char
*
args
;
ValueType
ret_type
;
Value
*
(
*
expr_fn
)(
void
*
sheet
,
GList
*
expr_node_list
,
int
eval_col
,
int
eval_row
,
char
**
error_string
);
Value
*
(
*
fn
)(
int
argc
,
Value
*
argv
[],
char
**
error_string
);
}
FunctionDefinition
;
/* For communication with yyparse */
extern
char
*
parser_expr
;
extern
ParseErr
parser_error
;
...
...
@@ -109,7 +138,9 @@ Value *value_cast_to_float (Value *v);
void
value_dump
(
Value
*
value
);
char
*
value_string
(
Value
*
value
);
float_t
value_get_as_double
(
Value
*
v
);
int
yyparse
(
void
);
void
functions_init
(
void
);
#endif
src/func.c
View file @
86c717b2
...
...
@@ -8,21 +8,210 @@
*/
#include
<config.h>
#include
<gnome.h>
#include
"math.h"
#include
"gnumeric.h"
#include
"gnumeric-sheet.h"
#include
"utils.h"
static
void
gnumeric_
sin
(
void
)
static
Value
*
gnumeric_
abs
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
printf
(
"Sinning
\n
"
);
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
fabs
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_acos
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
((
t
<
-
1
.
0
)
||
(
t
>
1
.
0
)){
*
error_string
=
_
(
"acos - domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
acos
(
t
);
return
v
;
}
static
Value
*
gnumeric_asin
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
((
t
<
-
1
.
0
)
||
(
t
>
1
.
0
)){
*
error_string
=
_
(
"asin - domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
asin
(
t
);
return
v
;
}
static
Value
*
gnumeric_atan
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
atan
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_atan2
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
atan2
(
value_get_as_double
(
argv
[
0
]),
value_get_as_double
(
argv
[
1
]));
return
v
;
}
static
Value
*
gnumeric_ceil
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
ceil
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_cos
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
cos
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_exp
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
exp
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_floor
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
floor
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_int
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
t
>
0
.
0
?
floor
(
t
)
:
ceil
(
t
);
return
v
;
}
static
Value
*
gnumeric_log
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
log
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_log10
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
log10
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_sin
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
sin
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_tan
(
int
argc
,
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
tan
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_pi
(
int
argc
,
Value
*
argv
[],
char
*
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
M_PI
;
return
v
;
}
static
struct
{
char
*
name
;
void
(
*
fn
)(
void
);
}
internal_functions
[]
=
{
{
"sin"
,
gnumeric_sin
},
FunctionDefinition
internal_functions
[]
=
{
{
"abs"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_abs
},
{
"acos"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_acos
},
{
"asin"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_asin
},
{
"atan"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_atan
},
{
"atan2"
,
"ff"
,
VALUE_FLOAT
,
NULL
,
gnumeric_atan2
},
{
"cos"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_cos
},
{
"ceil"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_ceil
},
{
"exp"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_exp
},
{
"floor"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_floor
},
{
"int"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_int
},
{
"log"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_log
},
{
"log10"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_log10
},
{
"sin"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_sin
},
{
"tan"
,
"f"
,
VALUE_FLOAT
,
NULL
,
gnumeric_tan
},
{
"pi"
,
""
,
VALUE_FLOAT
,
NULL
,
gnumeric_pi
},
{
NULL
,
NULL
},
};
...
...
@@ -32,7 +221,8 @@ functions_init (void)
int
i
;
for
(
i
=
0
;
internal_functions
[
i
].
name
;
i
++
){
symbol_install
(
internal_functions
[
i
].
name
,
SYMBOL_FUNCTION
,
internal_functions
[
i
].
fn
);
symbol_install
(
internal_functions
[
i
].
name
,
SYMBOL_FUNCTION
,
&
internal_functions
[
i
]);
}
}
src/item-bar.c
View file @
86c717b2
...
...
@@ -11,6 +11,7 @@
#include
<gnome.h>
#include
"gnumeric.h"
#include
"gnumeric-sheet.h"
#include
"item-bar.h"
#include
"item-debug.h"
...
...
@@ -265,27 +266,38 @@ set_cursor (ItemBar *item_bar, int pos)
}
static
void
item_bar_start_resize
(
ItemBar
*
item_bar
,
int
pos
)
item_bar_start_resize
(
ItemBar
*
item_bar
,
int
pos
,
int
pixels
)
{
GnomeCanvas
*
canvas
=
GNOME_CANVAS
(
item_bar
->
sheet
->
sheet_view
);
GnomeCanvasGroup
*
group
=
GNOME_CANVAS_GROUP
(
canvas
->
root
);
GnomeCanvasItem
*
item
;
GnomeCanvasPoints
*
points
;
GnumericSheet
*
gsheet
;
double
x1
,
x2
,
y1
,
y2
;
int
division_pos
;
gsheet
=
GNUMERIC_SHEET
(
item_bar
->
sheet
->
sheet_view
);
if
(
item_bar
->
orientation
==
GTK_ORIENTATION_VERTICAL
){
division_pos
=
sheet_col_get_distance
(
item_bar
->
sheet
,
gsheet
->
top_row
,
pos
);
x1
=
0
.
0
;
x2
=
INT_MAX
;
y1
=
GNOME_CANVAS_ITEM
(
item_bar
)
->
y1
+
pos
;
y2
=
GNOME_CANVAS_ITEM
(
item_bar
)
->
y1
+
pos
;
x2
=
canvas
->
width
;
y1
=
division_pos
;
y2
=
division_pos
;
}
else
{
division_pos
=
sheet_row_get_distance
(
item_bar
->
sheet
,
gsheet
->
top_col
,
pos
);
x1
=
division_pos
;
x2
=
division_pos
;
y1
=
0
.
0
;
y2
=
canvas
->
height
;
}
x1
=
0
.
0
;
x2
=
1000
.
0
;
y1
=
0
.
0
;
y2
=
1000
.
0
;
item_bar
->
resize_guide_offset
=
division_pos
-
pixels
;
/* Add a guideline to the sheet canvas */
points
=
gnome_canvas_points_new
(
2
);
points
->
coords
[
0
]
=
x1
;
...
...
@@ -296,7 +308,7 @@ item_bar_start_resize (ItemBar *item_bar, int pos)
gnome_canvas_line_get_type
(),
"points"
,
points
,
"fill_color"
,
"black"
,
"width_pixels"
,
4
,
"width_pixels"
,
1
,
NULL
);
gnome_canvas_points_free
(
points
);
...
...
@@ -349,22 +361,22 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
case
GDK_MOTION_NOTIFY
:
convert
(
canvas
,
e
->
motion
.
x
,
e
->
motion
.
y
,
&
x
,
&
y
);
if
(
item_bar
->
orientation
==
GTK_ORIENTATION_VERTICAL
)
if
(
item_bar
->
orientation
==
GTK_ORIENTATION_VERTICAL
)
{
pos
=
y
;
else
}
else
{
pos
=
x
;
}
/* Do column resizing or incremental marking */
if
(
resizing
){
int
npos
;
npos
=
pos
-
item_bar
->
resize_start_pos
;
if
(
npos
>
0
){
item_bar
->
resize_width
=
npos
;
gnome_canvas_request_redraw
(
GNOME_CANVAS_ITEM
(
item_bar
)
->
canvas
,
0
,
0
,
INT_MAX
,
INT_MAX
);
}
if
(
npos
<=
0
)
break
;
item_bar
->
resize_width
=
npos
;
gnome_canvas_request_redraw
(
GNOME_CANVAS_ITEM
(
item_bar
)
->
canvas
,
0
,
0
,
INT_MAX
,
INT_MAX
);
gnome_canvas_item_move
(
GNOME_CANVAS_ITEM
(
item_bar
->
resize_guide
),
0
,
pos
);
}
else
if
(
ITEM_BAR_IS_SELECTING
(
item_bar
)){
element
=
get_col_from_pos
(
item_bar
,
pos
);
...
...
@@ -390,9 +402,10 @@ item_bar_event (GnomeCanvasItem *item, GdkEvent *e)
item_bar
->
resize_start_pos
=
start
-
cri
->
pixels
;
item_bar
->
resize_width
=
cri
->
pixels
;
item_bar_start_resize
(
item_bar
,
pos
);
item_bar_start_resize
(
item_bar
,
element
,
pos
);
gnome_canvas_item_grab
(
item
,
GDK_POINTER_MOTION_MASK
|
GDK_BUTTON_RELEASE_MASK
,
GDK_POINTER_MOTION_MASK
|
GDK_BUTTON_RELEASE_MASK
,
item_bar
->
change_cursor
,
e
->
button
.
time
);
}
else
{
...
...
src/item-bar.h
View file @
86c717b2
...
...
@@ -20,7 +20,8 @@ typedef struct {
int
resize_width
;
int
resize_start_pos
;
GtkObject
*
resize_guide
;
int
resize_guide_offset
;
int
dragging
:
1
;
int
start_selection
;
}
ItemBar
;
...
...
src/parser.y
View file @
86c717b2
...
...
@@ -129,16 +129,7 @@ exp: NUMBER { $$ = $1 }
| CELLREF ':' CELLREF {}
| FUNCALL '(' arg_list ')' {
GList *l;
int i;
for (i = 0, l = $3; l; l = l->next){
printf ("Arg %d\n", i++);
dump_tree (l->data);
}
$$ = p_new (ExprTree);
$$->oper = OP_FUNCALL;
$$->u.function.symbol = $1->u.function.symbol;
$$ = $1;
$$->u.function.arg_list = $3;
}
;
...
...
@@ -151,7 +142,8 @@ arg_list: exp {
forget_glist ($3);
$$ = g_list_prepend ($3, $1);
alloc_glist ($$);
}
}
| { $$ = NULL; }
;
%%
...
...
@@ -224,27 +216,35 @@ static int
return_symbol (char *string)
{
ExprTree *e = p_new (ExprTree);
Value *v = v_new ();
Symbol *sym;
int type;
sym = symbol_lookup (string);
type = STRING;
if (!sym){
Value *v = v_new ();
v->v.str = string_get (string);
v->type = VALUE_STRING;
register_string (v->v.str);
e->oper = OP_CONSTANT;
e->u.constant = v;
} else {
symbol_ref (sym);
if (sym->type == SYMBOL_FUNCTION)
type = FUNCALL;
v->v.sym = sym;
register_symbol (v->v.sym);
else {
g_warning ("Unreachable\n");
type = -1;
}
e->oper = OP_FUNCALL;
e->u.function.symbol = sym;
e->u.function.arg_list = NULL;
register_symbol (sym);
}
v->type = VALUE_STRING;
e->oper = OP_CONSTANT;
e->u.constant = v;
yylval.tree = e;
return type;
}
...
...
src/symbol.c
View file @
86c717b2
...
...
@@ -119,8 +119,14 @@ symbol_unref (Symbol *sym)
}
}
gint
g_strcase_equal
(
gconstpointer
v1
,
gconstpointer
v2
)
{
return
strcasecmp
((
const
gchar
*
)
v1
,
(
const
gchar
*
)
v2
)
==
0
;
}
void
symbol_init
(
void
)
{
symbol_hash_table
=
g_hash_table_new
(
g_str_hash
,
g_str_equal
);
symbol_hash_table
=
g_hash_table_new
(
g_str_hash
,
g_str
case
_equal
);
}
Write
Preview