Allow values of multiple types
2000-08-07 Bradford Hovinen <hovinen@helixcode.com> * expr.c: Allow values of multiple types * main.c (main): Don't initialize glade
This commit is contained in:
parent
148d8186a5
commit
122042e532
4 changed files with 176 additions and 55 deletions
|
@ -1,5 +1,9 @@
|
||||||
2000-08-07 Bradford Hovinen <hovinen@helixcode.com>
|
2000-08-07 Bradford Hovinen <hovinen@helixcode.com>
|
||||||
|
|
||||||
|
* expr.c: Allow values of multiple types
|
||||||
|
|
||||||
|
* main.c (main): Don't initialize glade
|
||||||
|
|
||||||
* screensaver-prefs-dialog.c (screensaver_prefs_dialog_destroy):
|
* screensaver-prefs-dialog.c (screensaver_prefs_dialog_destroy):
|
||||||
Free structures only if they were ever allocated
|
Free structures only if they were ever allocated
|
||||||
|
|
||||||
|
|
|
@ -27,21 +27,39 @@
|
||||||
|
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
static gdouble int_parse_sentence (GScanner *scanner);
|
typedef enum {
|
||||||
static gdouble int_parse_unary (GScanner *scanner);
|
TYPE_BOOLEAN, TYPE_DOUBLE, TYPE_STRING
|
||||||
static gdouble int_parse_atom (GScanner *scanner);
|
} value_type_t;
|
||||||
static gdouble int_parse_expr (GScanner *scanner, gboolean expr,
|
|
||||||
|
typedef struct {
|
||||||
|
value_type_t type;
|
||||||
|
union {
|
||||||
|
gboolean v_bool;
|
||||||
|
gdouble v_double;
|
||||||
|
gchar *v_string;
|
||||||
|
} u;
|
||||||
|
} value_t;
|
||||||
|
|
||||||
|
static value_t int_parse_sentence (GScanner *scanner);
|
||||||
|
static value_t int_parse_unary (GScanner *scanner);
|
||||||
|
static value_t int_parse_atom (GScanner *scanner);
|
||||||
|
static value_t int_parse_expr (GScanner *scanner, gboolean expr,
|
||||||
gboolean neg);
|
gboolean neg);
|
||||||
static gdouble int_parse_term (GScanner *scanner, gboolean expr,
|
static value_t int_parse_term (GScanner *scanner, gboolean expr,
|
||||||
gboolean inv);
|
gboolean inv);
|
||||||
static gdouble int_parse_factor (GScanner *scanner, gboolean expr);
|
static value_t int_parse_factor (GScanner *scanner, gboolean expr);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
parse_sentence (gchar *sentence, GScanner *scanner)
|
parse_sentence (gchar *sentence, GScanner *scanner)
|
||||||
{
|
{
|
||||||
|
value_t val;
|
||||||
|
|
||||||
g_scanner_input_text (scanner, sentence, strlen (sentence));
|
g_scanner_input_text (scanner, sentence, strlen (sentence));
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return int_parse_sentence (scanner) != 0.0;
|
val = int_parse_sentence (scanner);
|
||||||
|
g_assert (val.type == TYPE_BOOLEAN);
|
||||||
|
|
||||||
|
return val.u.v_bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
gdouble
|
gdouble
|
||||||
|
@ -50,7 +68,7 @@ parse_expr (gchar *expr, gdouble var)
|
||||||
static GScannerConfig config;
|
static GScannerConfig config;
|
||||||
GScanner *scanner;
|
GScanner *scanner;
|
||||||
gchar *var_string;
|
gchar *var_string;
|
||||||
gfloat ret;
|
value_t ret;
|
||||||
|
|
||||||
config.cset_skip_characters = " \t\n";
|
config.cset_skip_characters = " \t\n";
|
||||||
config.cset_identifier_first = "abcdefghijklmnopqrstuvwxyz";
|
config.cset_identifier_first = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
@ -66,20 +84,22 @@ parse_expr (gchar *expr, gdouble var)
|
||||||
g_scanner_scope_add_symbol (scanner, 0, "var", var_string);
|
g_scanner_scope_add_symbol (scanner, 0, "var", var_string);
|
||||||
|
|
||||||
ret = int_parse_expr (scanner, TRUE, FALSE);
|
ret = int_parse_expr (scanner, TRUE, FALSE);
|
||||||
|
g_assert (ret.type == TYPE_DOUBLE);
|
||||||
|
|
||||||
g_free (var_string);
|
g_free (var_string);
|
||||||
g_scanner_destroy (scanner);
|
g_scanner_destroy (scanner);
|
||||||
return ret;
|
return ret.u.v_double;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble
|
static value_t
|
||||||
int_parse_sentence (GScanner *scanner)
|
int_parse_sentence (GScanner *scanner)
|
||||||
{
|
{
|
||||||
GTokenType token_type;
|
GTokenType token_type;
|
||||||
GTokenValue value;
|
GTokenValue value;
|
||||||
gdouble left;
|
value_t left, right;
|
||||||
|
|
||||||
left = int_parse_unary (scanner);
|
left = int_parse_unary (scanner);
|
||||||
|
g_assert (left.type == TYPE_BOOLEAN);
|
||||||
|
|
||||||
token_type = g_scanner_cur_token (scanner);
|
token_type = g_scanner_cur_token (scanner);
|
||||||
value = g_scanner_cur_value (scanner);
|
value = g_scanner_cur_value (scanner);
|
||||||
|
@ -88,26 +108,31 @@ int_parse_sentence (GScanner *scanner)
|
||||||
(token_type == G_TOKEN_SYMBOL && value.v_symbol == SYMBOL_AND))
|
(token_type == G_TOKEN_SYMBOL && value.v_symbol == SYMBOL_AND))
|
||||||
{
|
{
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return (int_parse_sentence (scanner) != 0.0 &&
|
right = int_parse_sentence (scanner);
|
||||||
left != 0.0) ? 1.0 : 0.0;
|
g_assert (right.type == TYPE_BOOLEAN);
|
||||||
|
left.u.v_bool = left.u.v_bool && right.u.v_bool;
|
||||||
|
return left;
|
||||||
}
|
}
|
||||||
else if ((token_type == G_TOKEN_CHAR && value.v_char == '|') ||
|
else if ((token_type == G_TOKEN_CHAR && value.v_char == '|') ||
|
||||||
(token_type == G_TOKEN_SYMBOL &&
|
(token_type == G_TOKEN_SYMBOL &&
|
||||||
value.v_symbol == SYMBOL_OR))
|
value.v_symbol == SYMBOL_OR))
|
||||||
{
|
{
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return (int_parse_sentence (scanner) != 0.0 ||
|
right = int_parse_sentence (scanner);
|
||||||
left != 0.0) ? 1.0 : 0.0;
|
g_assert (right.type == TYPE_BOOLEAN);
|
||||||
|
left.u.v_bool = left.u.v_bool || right.u.v_bool;
|
||||||
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble
|
static value_t
|
||||||
int_parse_unary (GScanner *scanner)
|
int_parse_unary (GScanner *scanner)
|
||||||
{
|
{
|
||||||
GTokenType token_type;
|
GTokenType token_type;
|
||||||
GTokenValue value;
|
GTokenValue value;
|
||||||
|
value_t op;
|
||||||
|
|
||||||
token_type = g_scanner_cur_token (scanner);
|
token_type = g_scanner_cur_token (scanner);
|
||||||
value = g_scanner_cur_value (scanner);
|
value = g_scanner_cur_value (scanner);
|
||||||
|
@ -116,18 +141,23 @@ int_parse_unary (GScanner *scanner)
|
||||||
(token_type == G_TOKEN_SYMBOL && value.v_symbol == SYMBOL_NOT))
|
(token_type == G_TOKEN_SYMBOL && value.v_symbol == SYMBOL_NOT))
|
||||||
{
|
{
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return (int_parse_unary (scanner) != 0.0) ? 0.0 : 1.0;
|
op = int_parse_unary (scanner);
|
||||||
|
g_assert (op.type == TYPE_BOOLEAN);
|
||||||
|
op.u.v_bool = !op.u.v_bool;
|
||||||
|
return op;
|
||||||
} else {
|
} else {
|
||||||
return (int_parse_atom (scanner) != 0.0) ? 1.0 : 0.0;
|
op = int_parse_atom (scanner);
|
||||||
|
g_assert (op.type == TYPE_BOOLEAN);
|
||||||
|
return op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble
|
static value_t
|
||||||
int_parse_atom (GScanner *scanner)
|
int_parse_atom (GScanner *scanner)
|
||||||
{
|
{
|
||||||
GTokenType token_type;
|
GTokenType token_type;
|
||||||
GTokenValue value;
|
GTokenValue value;
|
||||||
gdouble left;
|
value_t left, right;
|
||||||
|
|
||||||
left = int_parse_expr (scanner, FALSE, FALSE);
|
left = int_parse_expr (scanner, FALSE, FALSE);
|
||||||
|
|
||||||
|
@ -137,31 +167,58 @@ int_parse_atom (GScanner *scanner)
|
||||||
value = g_scanner_cur_value (scanner);
|
value = g_scanner_cur_value (scanner);
|
||||||
if (value.v_char == '=') {
|
if (value.v_char == '=') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return (int_parse_expr (scanner, FALSE, FALSE)
|
right = int_parse_expr (scanner, FALSE, FALSE);
|
||||||
== left) ? 1.0 : 0.0;
|
|
||||||
|
if (left.type != right.type)
|
||||||
|
left.u.v_bool = FALSE;
|
||||||
|
else if (left.type == TYPE_DOUBLE)
|
||||||
|
left.u.v_bool = (left.u.v_double ==
|
||||||
|
right.u.v_double);
|
||||||
|
else if (left.type == TYPE_STRING)
|
||||||
|
left.u.v_bool =
|
||||||
|
(strcmp (left.u.v_string,
|
||||||
|
right.u.v_string) == 0);
|
||||||
}
|
}
|
||||||
else if (value.v_char == '<') {
|
else if (value.v_char == '<') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return (int_parse_expr (scanner, FALSE, FALSE)
|
right = int_parse_expr (scanner, FALSE, FALSE);
|
||||||
> left) ? 1.0 : 0.0;
|
|
||||||
|
if (left.type != TYPE_DOUBLE ||
|
||||||
|
right.type != TYPE_DOUBLE)
|
||||||
|
left.u.v_bool = FALSE;
|
||||||
|
else
|
||||||
|
left.u.v_bool = (left.u.v_double <
|
||||||
|
right.u.v_double);
|
||||||
}
|
}
|
||||||
else if (value.v_char == '>') {
|
else if (value.v_char == '>') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return (int_parse_expr (scanner, FALSE, FALSE)
|
right = int_parse_expr (scanner, FALSE, FALSE);
|
||||||
< left) ? 1.0 : 0.0;
|
|
||||||
|
if (left.type != TYPE_DOUBLE ||
|
||||||
|
right.type != TYPE_DOUBLE)
|
||||||
|
left.u.v_bool = FALSE;
|
||||||
|
else
|
||||||
|
left.u.v_bool = (left.u.v_double >
|
||||||
|
right.u.v_double);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (left.type == TYPE_DOUBLE)
|
||||||
|
left.u.v_bool = (left.u.v_double != 0.0);
|
||||||
|
else if (left.type == TYPE_STRING)
|
||||||
|
left.u.v_bool = (left.u.v_string != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
left.type = TYPE_BOOLEAN;
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble
|
static value_t
|
||||||
int_parse_expr (GScanner *scanner, gboolean expr, gboolean neg)
|
int_parse_expr (GScanner *scanner, gboolean expr, gboolean neg)
|
||||||
{
|
{
|
||||||
GTokenType token_type;
|
GTokenType token_type;
|
||||||
GTokenValue value;
|
GTokenValue value;
|
||||||
gdouble left;
|
value_t left, right;
|
||||||
gdouble ret;
|
|
||||||
|
|
||||||
left = int_parse_term (scanner, expr, FALSE);
|
left = int_parse_term (scanner, expr, FALSE);
|
||||||
|
|
||||||
|
@ -171,28 +228,41 @@ int_parse_expr (GScanner *scanner, gboolean expr, gboolean neg)
|
||||||
value = g_scanner_cur_value (scanner);
|
value = g_scanner_cur_value (scanner);
|
||||||
if (value.v_char == '+') {
|
if (value.v_char == '+') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return left + int_parse_expr (scanner, expr, FALSE);
|
right = int_parse_expr (scanner, expr, FALSE);
|
||||||
|
|
||||||
|
if (left.type != TYPE_DOUBLE ||
|
||||||
|
right.type != TYPE_DOUBLE)
|
||||||
|
left.u.v_double = 0.0;
|
||||||
|
else
|
||||||
|
left.u.v_double += right.u.v_double;
|
||||||
|
|
||||||
|
left.type = TYPE_DOUBLE;
|
||||||
}
|
}
|
||||||
else if (value.v_char == '-') {
|
else if (value.v_char == '-') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
ret = int_parse_expr (scanner, expr, TRUE);
|
right = int_parse_expr (scanner, expr, TRUE);
|
||||||
if (neg)
|
|
||||||
return left + ret;
|
if (left.type != TYPE_DOUBLE ||
|
||||||
|
right.type != TYPE_DOUBLE)
|
||||||
|
left.u.v_double = 0.0;
|
||||||
|
else if (neg)
|
||||||
|
left.u.v_double += right.u.v_double;
|
||||||
else
|
else
|
||||||
return left - ret;
|
left.u.v_double -= right.u.v_double;
|
||||||
|
|
||||||
|
left.type = TYPE_DOUBLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble
|
static value_t
|
||||||
int_parse_term (GScanner *scanner, gboolean expr, gboolean inv)
|
int_parse_term (GScanner *scanner, gboolean expr, gboolean inv)
|
||||||
{
|
{
|
||||||
GTokenType token_type;
|
GTokenType token_type;
|
||||||
GTokenValue value;
|
GTokenValue value;
|
||||||
gdouble left;
|
value_t left, right;
|
||||||
gdouble ret;
|
|
||||||
|
|
||||||
left = int_parse_factor (scanner, expr);
|
left = int_parse_factor (scanner, expr);
|
||||||
|
|
||||||
|
@ -202,27 +272,41 @@ int_parse_term (GScanner *scanner, gboolean expr, gboolean inv)
|
||||||
value = g_scanner_cur_value (scanner);
|
value = g_scanner_cur_value (scanner);
|
||||||
if (token_type == '*') {
|
if (token_type == '*') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
return left * int_parse_term (scanner, expr, FALSE);
|
right = int_parse_term (scanner, expr, FALSE);
|
||||||
|
|
||||||
|
if (left.type != TYPE_DOUBLE ||
|
||||||
|
right.type != TYPE_DOUBLE)
|
||||||
|
left.u.v_double = 0.0;
|
||||||
|
else
|
||||||
|
left.u.v_double *= right.u.v_double;
|
||||||
|
|
||||||
|
left.type = TYPE_DOUBLE;
|
||||||
}
|
}
|
||||||
else if (token_type == '/') {
|
else if (token_type == '/') {
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
ret = int_parse_term (scanner, expr, TRUE);
|
right = int_parse_expr (scanner, expr, TRUE);
|
||||||
if (inv)
|
|
||||||
return left * ret;
|
if (left.type != TYPE_DOUBLE ||
|
||||||
|
right.type != TYPE_DOUBLE)
|
||||||
|
left.u.v_double = 0.0;
|
||||||
|
else if (inv)
|
||||||
|
left.u.v_double *= right.u.v_double;
|
||||||
else
|
else
|
||||||
return left / ret;
|
left.u.v_double /= right.u.v_double;
|
||||||
|
|
||||||
|
left.type = TYPE_DOUBLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gdouble
|
static value_t
|
||||||
int_parse_factor (GScanner *scanner, gboolean expr)
|
int_parse_factor (GScanner *scanner, gboolean expr)
|
||||||
{
|
{
|
||||||
GTokenType token_type;
|
GTokenType token_type;
|
||||||
GTokenValue value;
|
GTokenValue value;
|
||||||
gdouble ret;
|
value_t ret;
|
||||||
|
|
||||||
token_type = g_scanner_cur_token (scanner);
|
token_type = g_scanner_cur_token (scanner);
|
||||||
value = g_scanner_cur_value (scanner);
|
value = g_scanner_cur_value (scanner);
|
||||||
|
@ -235,25 +319,42 @@ int_parse_factor (GScanner *scanner, gboolean expr)
|
||||||
ret = int_parse_sentence (scanner);
|
ret = int_parse_sentence (scanner);
|
||||||
|
|
||||||
g_scanner_get_next_token (scanner);
|
g_scanner_get_next_token (scanner);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else if (token_type == G_TOKEN_INT) {
|
else if (token_type == G_TOKEN_INT) {
|
||||||
return value.v_int;
|
ret.type = TYPE_DOUBLE;
|
||||||
|
ret.u.v_double = (gdouble) value.v_int;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
else if (token_type == G_TOKEN_FLOAT) {
|
else if (token_type == G_TOKEN_FLOAT) {
|
||||||
return value.v_float;
|
ret.type = TYPE_DOUBLE;
|
||||||
|
ret.u.v_double = (gdouble) value.v_float;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
else if (token_type == G_TOKEN_SYMBOL) {
|
else if (token_type == G_TOKEN_SYMBOL) {
|
||||||
if (value.v_symbol == (gpointer) 1)
|
if (value.v_symbol == (gpointer) 1) {
|
||||||
return (gint) value.v_symbol;
|
ret.type = TYPE_DOUBLE;
|
||||||
else
|
ret.u.v_double = 1.0;
|
||||||
return g_strtod (value.v_symbol, NULL);
|
} else {
|
||||||
|
ret.type = TYPE_DOUBLE;
|
||||||
|
ret.u.v_double = g_strtod (value.v_symbol, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
else if (token_type == G_TOKEN_IDENTIFIER) {
|
else if (token_type == G_TOKEN_IDENTIFIER) {
|
||||||
return 0.0;
|
ret.type = TYPE_STRING;
|
||||||
|
ret.u.v_string = value.v_identifier;
|
||||||
|
|
||||||
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
g_scanner_error (scanner, "Parse error in expression");
|
g_scanner_error (scanner, "Parse error in expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret.type = TYPE_BOOLEAN;
|
||||||
|
ret.u.v_bool = FALSE;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,8 +190,6 @@ main (int argc, char **argv)
|
||||||
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
|
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
|
||||||
textdomain (PACKAGE);
|
textdomain (PACKAGE);
|
||||||
|
|
||||||
glade_gnome_init ();
|
|
||||||
|
|
||||||
res = gnome_capplet_init ("screensaver-properties",
|
res = gnome_capplet_init ("screensaver-properties",
|
||||||
VERSION, argc, argv, NULL,
|
VERSION, argc, argv, NULL,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
SUBDIRS = fr
|
INCLUDES = \
|
||||||
|
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
|
||||||
|
$(GNOME_INCLUDEDIR) \
|
||||||
|
$(XML_CFLAGS) \
|
||||||
|
-I$(top_srcdir)/
|
||||||
|
|
||||||
Screensaversdir = $(datadir)/screensavers
|
Screensaversdir = $(datadir)/screensavers
|
||||||
Screensavers_DATA = \
|
Screensavers_DATA = \
|
||||||
|
@ -6,3 +10,17 @@ Screensavers_DATA = \
|
||||||
attraction.xml
|
attraction.xml
|
||||||
|
|
||||||
EXTRA_DIST = $(Screensavers_DATA)
|
EXTRA_DIST = $(Screensavers_DATA)
|
||||||
|
|
||||||
|
noinst_PROGRAMS = extract-labels
|
||||||
|
|
||||||
|
extract_labels_SOURCES = extract-labels.c
|
||||||
|
|
||||||
|
extract_labels_LDADD = \
|
||||||
|
$(GNOME_LIBDIR) \
|
||||||
|
$(GNOME_LIBS) \
|
||||||
|
$(GNOME_XML_LIB)
|
||||||
|
|
||||||
|
qix.xml.h: qix.xml extract-labels
|
||||||
|
./extract-labels qix.xml
|
||||||
|
attraction.xml.h: attraction.xml extract-labels
|
||||||
|
./extract-labels attraction.xml
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue