summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2017-10-22 01:45:33 +0200
committerBenjamin Otte <otte@redhat.com>2017-10-30 02:58:03 +0100
commit7e9aa97fd5581639ea13fdbb2b6f196359406e9d (patch)
tree70ca5561a66080d967d93a455deac46bff31dfd8
parent38bc5f3d37e2caaf1b95bcc198a231adb42012d8 (diff)
downloadgtk+-7e9aa97fd5581639ea13fdbb2b6f196359406e9d.tar.gz
gsksl: Add gsk_sl_expression_parse_integral_constant()
This is for parsing constant expressions, like array indices or layout specifiers.
-rw-r--r--gsk/gskslexpression.c74
-rw-r--r--gsk/gskslexpressionprivate.h4
-rw-r--r--gsk/gskslqualifier.c36
3 files changed, 79 insertions, 35 deletions
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 21cb1d1cc9..5b2c7bb5a4 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -2890,6 +2890,80 @@ gsk_sl_expression_parse_constant (GskSlScope *scope,
return gsk_sl_expression_parse_conditional (scope, stream);
}
+gint32
+gsk_sl_expression_parse_integral_constant (GskSlScope *scope,
+ GskSlPreprocessor *preproc,
+ gint32 minimum,
+ guint32 maximum)
+{
+ GskSlExpression *expression;
+ GskSlValue *value;
+ GskSlType *type;
+
+ g_return_val_if_fail (minimum < maximum, minimum);
+
+ expression = gsk_sl_expression_parse_constant (scope, preproc);
+ value = gsk_sl_expression_get_constant (expression);
+ gsk_sl_expression_unref (expression);
+
+ if (value == NULL)
+ {
+ gsk_sl_preprocessor_error (preproc, CONSTANT, "Expression is not constant.");
+ return minimum;
+ }
+
+ type = gsk_sl_value_get_type (value);
+ if (gsk_sl_type_is_scalar (type) && gsk_sl_type_get_scalar_type (type) == GSK_SL_INT)
+ {
+ gint32 i = *(gint32 *) gsk_sl_value_get_data (value);
+
+ if (i < minimum)
+ {
+ gsk_sl_preprocessor_error (preproc, CONSTANT,
+ "Constant expression evaluates to %d, but must be at least %d.",
+ i, minimum);
+ i = minimum;
+ }
+ else if (i > 0 && i > maximum)
+ {
+ gsk_sl_preprocessor_error (preproc, CONSTANT,
+ "Constant expression evaluates to %d, but must be at most %d.",
+ i, maximum);
+ i = maximum;
+ }
+
+ return i;
+ }
+ else if (gsk_sl_type_is_scalar (type) && gsk_sl_type_get_scalar_type (type) == GSK_SL_UINT)
+ {
+ guint32 u;
+
+ u = *(guint32 *) gsk_sl_value_get_data (value);
+
+ if (minimum >= 0 && u < minimum)
+ {
+ gsk_sl_preprocessor_error (preproc, CONSTANT,
+ "Constant expression evaluates to %u, but must be at least %d.",
+ u, minimum);
+ u = minimum;
+ }
+ else if (u > maximum)
+ {
+ gsk_sl_preprocessor_error (preproc, CONSTANT,
+ "Constant expression evaluates to %u, but must be at most %d.",
+ u, maximum);
+ u = maximum;
+ }
+
+ return u;
+ }
+ else
+ {
+ gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Type of expression is not an integer type, but %s", gsk_sl_type_get_name (type));
+ return minimum;
+ }
+}
+
GskSlExpression *
gsk_sl_expression_parse_assignment (GskSlScope *scope,
GskSlPreprocessor *preproc)
diff --git a/gsk/gskslexpressionprivate.h b/gsk/gskslexpressionprivate.h
index d9dc7a3a2d..080e5995bb 100644
--- a/gsk/gskslexpressionprivate.h
+++ b/gsk/gskslexpressionprivate.h
@@ -29,6 +29,10 @@ GskSlExpression * gsk_sl_expression_parse_assignment (GskSlScope
GskSlPreprocessor *stream);
GskSlExpression * gsk_sl_expression_parse_constant (GskSlScope *scope,
GskSlPreprocessor *stream);
+gint32 gsk_sl_expression_parse_integral_constant (GskSlScope *scope,
+ GskSlPreprocessor *preproc,
+ gint32 minimum,
+ guint32 maximum);
GskSlExpression * gsk_sl_expression_parse_constructor (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlType *type);
diff --git a/gsk/gskslqualifier.c b/gsk/gskslqualifier.c
index cf0bf89d63..60c3004308 100644
--- a/gsk/gskslqualifier.c
+++ b/gsk/gskslqualifier.c
@@ -40,10 +40,7 @@ gsk_sl_qualifier_parse_layout_assignment (GskSlPreprocessor *preproc,
GskSlScope *scope,
int *target)
{
- GskSlExpression *expression;
const GskSlToken *token;
- GskSlValue *value;
- GskSlType *type;
gsk_sl_preprocessor_consume (preproc, NULL);
@@ -55,38 +52,7 @@ gsk_sl_qualifier_parse_layout_assignment (GskSlPreprocessor *preproc,
}
gsk_sl_preprocessor_consume (preproc, NULL);
- expression = gsk_sl_expression_parse_constant (scope, preproc);
- if (expression == NULL)
- return;
-
- value = gsk_sl_expression_get_constant (expression);
- gsk_sl_expression_unref (expression);
-
- if (value == NULL)
- {
- gsk_sl_preprocessor_error (preproc, CONSTANT, "Expression is not constant.");
- return;
- }
-
- type = gsk_sl_value_get_type (value);
- if (gsk_sl_type_is_scalar (type) && gsk_sl_type_get_scalar_type (type) == GSK_SL_INT)
- {
- gint32 i = *(gint32 *) gsk_sl_value_get_data (value);
-
- if (i < 0)
- gsk_sl_preprocessor_error (preproc, CONSTANT, "Expression may not be negative.");
- else
- *target = i;
- }
- else if (gsk_sl_type_is_scalar (type) && gsk_sl_type_get_scalar_type (type) == GSK_SL_UINT)
- {
- *target = *(guint32 *) gsk_sl_value_get_data (value);
- }
- else
- {
- gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH, "Type of expression is not an integer type, but %s", gsk_sl_type_get_name (type));
- }
- gsk_sl_value_free (value);
+ *target = gsk_sl_expression_parse_integral_constant (scope, preproc, 0, G_MAXINT);
}
static void