mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-04 01:43:24 +00:00
plug-ins: new named argument syntax in Script-Fu.
This syntax is now the official syntax for non-core PDB procedures. I.e. that while core procedures will still use ordered arguments (e.g.: `(gimp-image-get-layers 1)`), plug-in PDB procedures called from Script-Fu will have named arguments in any order. Say for instance that you want to call python-fu-foggify from Script-Fu. Whereas we used to run: > (python-fu-foggify RUN-NONINTERACTIVE 1 (car (gimp-image-get-layers 1)) "Clouds" '(50 4 4) 1.0 50.0) Now we should call: > (python-fu-foggify #:image 1 #:drawables (car (gimp-image-get-layers 1)) #:opacity 50.0 #:color '(50 4 4)) Now we can note: * Every argument is preceded by a #:label which is the argument name. This makes these calls much more readable (some plug-in procedures can have dozen of arguments and these end up as list of integers, floats and strings, which are hard to read and hard to debug) and semantic. * Order doesn't matter anymore. For instance here, I put #:opacity before #:color. * As a direct consequence, we can drop any argument which we wish to keep with default value. E.g. in the old style, we had to put the #:run-mode, #:name ("Clouds") and #:turbulence (1.0) because we were changing the last argument #:opacity (50.0). Now we can drop all 3 default arguments. Having non-ordered argument is in fact the starter of this feature, because it is already the case for calling PDB procedures in the libgimp API (and therefore in all GIR bindings). By saying that the order of PDB procedures is not part of the API, we actually allow to add arguments and even to reorder them in the future without breaking existing scripts in the 3.0 series. This became even more serious when I was considering to make the generic metadata arguments public. Since they are appended to the end, after all plug-in-specific arguments, if I do this, adding any argument in an export plug-in would break order. It won't matter anymore! Note that it doesn't matter for core PDB procedures (where this syntax is not used) because these are also C functions and therefore order and number of arguments matter anyway. Also these don't have dozens of arguments. As a helper for Script-Fu developer, in particular as we already released 2 RCs and therefore some people already started to port their scripts, the old syntax will still work yet will produce a warning showing how to call the same thing with the new syntax. For instance, with the above first call, the warning will be: > (script-fu:2059912): scriptfu-WARNING **: 22:54:47.507: Calling Plug-In PDB procedures with arguments as an ordered list is deprecated. > Please use named arguments: (python-fu-foggify #:run-mode 1 #:image 1 #:drawables (2) #:name "Clouds" #:color '(50 4 4) #:turbulence 1.000000 #:opacity 50.000000) Note that the argument name syntax is coming from the Racket scheme variant: https://docs.racket-lang.org/arguments/index.html Common Lisp has a similar syntax, either with just a colon, or also a sharp + colon (it's unclear to me the difference, something about interned vs. uninterned symbols). After discussion with Liam on IRC, we decided to go with the #: syntax of Racket.
This commit is contained in:
parent
751665a7bd
commit
f92f7d425c
6 changed files with 448 additions and 105 deletions
|
@ -79,11 +79,13 @@ marshal_ID_to_item (scheme *sc,
|
|||
* Requires ID's of instances of GimpItem
|
||||
*/
|
||||
pointer
|
||||
marshal_vector_to_item_array (scheme *sc,
|
||||
pointer vector,
|
||||
GValue *value)
|
||||
marshal_vector_to_item_array (scheme *sc,
|
||||
pointer vector,
|
||||
GValue *value,
|
||||
gchar **strvalue)
|
||||
{
|
||||
GObject **object_array;
|
||||
GString *v = NULL;
|
||||
gint id;
|
||||
pointer error;
|
||||
|
||||
|
@ -92,6 +94,8 @@ marshal_vector_to_item_array (scheme *sc,
|
|||
/* empty vector will produce empty GimpObjectArray */
|
||||
|
||||
object_array = g_new0 (GObject *, num_elements + 1);
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (int j = 0; j < num_elements; ++j)
|
||||
{
|
||||
|
@ -100,6 +104,8 @@ marshal_vector_to_item_array (scheme *sc,
|
|||
if (!sc->vptr->is_number (element))
|
||||
{
|
||||
g_free (object_array);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return script_error (sc, "Expected numeric in vector of ID", vector);
|
||||
/* FUTURE more detailed error msg:
|
||||
* return script_type_error_in_container (sc, "numeric", i, j, proc_name, vector);
|
||||
|
@ -111,8 +117,13 @@ marshal_vector_to_item_array (scheme *sc,
|
|||
if (error)
|
||||
{
|
||||
g_free (object_array);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (v)
|
||||
g_string_append_printf (v, "%s%d", j == 0 ? "" : " ", id);
|
||||
}
|
||||
|
||||
/* Shallow copy.
|
||||
|
@ -122,6 +133,11 @@ marshal_vector_to_item_array (scheme *sc,
|
|||
* and fails if we default to G_TYPE_INVALID but passes if ITEM.
|
||||
*/
|
||||
g_value_set_boxed (value, (gpointer) object_array);
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
|
||||
g_free (object_array);
|
||||
|
||||
|
@ -258,12 +274,18 @@ get_item_from_ID_in_script (scheme *sc,
|
|||
* A list longer than expected (>4) is not an error, but extra list is not used.
|
||||
*/
|
||||
static void
|
||||
marshal_list_of_numeric_to_rgba (scheme *sc,
|
||||
pointer color_list,
|
||||
guchar (*rgba)[4], /* OUT */
|
||||
guint *length) /* OUT */
|
||||
marshal_list_of_numeric_to_rgba (scheme *sc,
|
||||
pointer color_list,
|
||||
guchar (*rgba)[4], /* OUT */
|
||||
guint *length, /* OUT */
|
||||
gchar **strvalue)
|
||||
{
|
||||
GString *v = NULL;
|
||||
|
||||
*length = 0;
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (guint i=0; i<4; i++)
|
||||
{
|
||||
if (sc->vptr->is_number (sc->vptr->pair_car (color_list)))
|
||||
|
@ -272,14 +294,31 @@ marshal_list_of_numeric_to_rgba (scheme *sc,
|
|||
0, 255);
|
||||
*length = *length + 1;
|
||||
color_list = sc->vptr->pair_cdr (color_list);
|
||||
|
||||
if (v)
|
||||
g_string_append_printf (v, "%s%d", i == 0 ? "" : " ", (*rgba)[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reached end of list or non-numeric. */
|
||||
if (v)
|
||||
{
|
||||
if (*length != 0)
|
||||
*strvalue = g_strdup_printf ("'(%s)", v->str);
|
||||
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* *length is in [0,4] and *rgba is filled in with same count. */
|
||||
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("'(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk a C array of bytes (rgba) creating Scheme list of numeric.
|
||||
|
@ -313,16 +352,15 @@ marshal_rgba_to_list_of_numeric (scheme *sc,
|
|||
* - list elements not numbers.
|
||||
*/
|
||||
GeglColor *
|
||||
marshal_component_list_to_color (scheme *sc,
|
||||
pointer color_list)
|
||||
marshal_component_list_to_color (scheme *sc,
|
||||
pointer color_list,
|
||||
gchar **strvalue)
|
||||
{
|
||||
GeglColor *color_result;
|
||||
guchar rgba[4];
|
||||
guint list_length;
|
||||
|
||||
|
||||
|
||||
marshal_list_of_numeric_to_rgba (sc, color_list, &rgba, &list_length);
|
||||
marshal_list_of_numeric_to_rgba (sc, color_list, &rgba, &list_length, strvalue);
|
||||
/* list_length is the count of numerics used. */
|
||||
|
||||
/* Dispatch on list length and create different format colors */
|
||||
|
|
|
@ -25,7 +25,8 @@ pointer marshal_ID_to_item (scheme *sc,
|
|||
|
||||
pointer marshal_vector_to_item_array (scheme *sc,
|
||||
pointer a,
|
||||
GValue *value);
|
||||
GValue *value,
|
||||
gchar **strvalue);
|
||||
|
||||
void marshal_path_string_to_gfile (scheme *sc,
|
||||
pointer a,
|
||||
|
@ -38,7 +39,8 @@ pointer marshal_returned_object_array_to_vector (scheme *sc,
|
|||
gchar* marshal_returned_gfile_to_string (GValue *value);
|
||||
|
||||
GeglColor* marshal_component_list_to_color (scheme *sc,
|
||||
pointer list);
|
||||
pointer list,
|
||||
gchar **strvalue);
|
||||
pointer marshal_color_to_component_list (scheme *sc,
|
||||
GeglColor *color);
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ static pointer script_fu_marshal_arg_to_value (scheme
|
|||
const gchar *proc_name,
|
||||
gint arg_index,
|
||||
GParamSpec *arg_spec,
|
||||
GValue *value);
|
||||
GValue *value,
|
||||
gchar **strvalue);
|
||||
|
||||
static pointer script_fu_marshal_procedure_call (scheme *sc,
|
||||
pointer a,
|
||||
|
@ -730,12 +731,13 @@ ts_load_file (const gchar *dirname,
|
|||
|
||||
/* Returns pointer to sc->NIL (normal) or pointer to error. */
|
||||
static pointer
|
||||
script_fu_marshal_arg_to_value (scheme *sc,
|
||||
pointer a,
|
||||
const gchar *proc_name,
|
||||
gint arg_index,
|
||||
GParamSpec *arg_spec,
|
||||
GValue *value)
|
||||
script_fu_marshal_arg_to_value (scheme *sc,
|
||||
pointer a,
|
||||
const gchar *proc_name,
|
||||
gint arg_index,
|
||||
GParamSpec *arg_spec,
|
||||
GValue *value,
|
||||
gchar **strvalue)
|
||||
{
|
||||
pointer arg_val;
|
||||
pointer vector;
|
||||
|
@ -763,6 +765,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
return script_int_range_error (sc, arg_index, proc_name, ispec->minimum, ispec->maximum, v);
|
||||
|
||||
g_value_set_int (value, v);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", v);
|
||||
}
|
||||
}
|
||||
else if (G_VALUE_HOLDS_UINT (value))
|
||||
|
@ -780,6 +784,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
return script_int_range_error (sc, arg_index, proc_name, ispec->minimum, ispec->maximum, v);
|
||||
|
||||
g_value_set_uint (value, v);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%u", v);
|
||||
}
|
||||
}
|
||||
else if (G_VALUE_HOLDS_UCHAR (value))
|
||||
|
@ -797,6 +803,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
return script_int_range_error (sc, arg_index, proc_name, cspec->minimum, cspec->maximum, c);
|
||||
|
||||
g_value_set_uchar (value, c);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", c);
|
||||
}
|
||||
}
|
||||
else if (G_VALUE_HOLDS_DOUBLE (value))
|
||||
|
@ -814,26 +822,38 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
return script_float_range_error (sc, arg_index, proc_name, dspec->minimum, dspec->maximum, d);
|
||||
|
||||
g_value_set_double (value, d);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%f", d);
|
||||
}
|
||||
}
|
||||
else if (G_VALUE_HOLDS_ENUM (value))
|
||||
{
|
||||
if (! sc->vptr->is_number (arg_val))
|
||||
return script_type_error (sc, "numeric", arg_index, proc_name);
|
||||
{
|
||||
return script_type_error (sc, "numeric", arg_index, proc_name);
|
||||
}
|
||||
else
|
||||
g_value_set_enum (value,
|
||||
sc->vptr->ivalue (arg_val));
|
||||
{
|
||||
gint e = sc->vptr->ivalue (arg_val);
|
||||
|
||||
g_value_set_enum (value, e);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", e);
|
||||
}
|
||||
}
|
||||
else if (G_VALUE_HOLDS_BOOLEAN (value))
|
||||
{
|
||||
if (sc->vptr->is_number (arg_val))
|
||||
{
|
||||
gboolean b = sc->vptr->ivalue (arg_val);
|
||||
|
||||
/* Bind according to C idiom: 0 is false, other numeric values true.
|
||||
* This is not strict Scheme: 0 is truthy in Scheme.
|
||||
* This lets FALSE still work, where FALSE is a deprecated symbol for 0.
|
||||
*/
|
||||
g_value_set_boolean (value,
|
||||
sc->vptr->ivalue (arg_val));
|
||||
g_value_set_boolean (value, b);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%s", b ? "TRUE" : "FALSE");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -847,6 +867,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
*/
|
||||
gboolean truth_value = ! (arg_val == sc->F);
|
||||
g_value_set_boolean (value, truth_value);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%s", truth_value ? "TRUE" : "FALSE");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -858,10 +880,21 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
else if (G_VALUE_HOLDS_STRING (value))
|
||||
{
|
||||
if (! sc->vptr->is_string (arg_val))
|
||||
return script_type_error (sc, "string", arg_index, proc_name);
|
||||
{
|
||||
return script_type_error (sc, "string", arg_index, proc_name);
|
||||
}
|
||||
else
|
||||
g_value_set_string (value,
|
||||
sc->vptr->string_value (arg_val));
|
||||
{
|
||||
const gchar *s = sc->vptr->string_value (arg_val);
|
||||
|
||||
g_value_set_string (value, s);
|
||||
if (strvalue)
|
||||
{
|
||||
gchar *escaped = g_strescape (s, NULL);
|
||||
*strvalue = g_strdup_printf ("\"%s\"", escaped);
|
||||
g_free (escaped);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
|
||||
{
|
||||
|
@ -872,11 +905,14 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
gchar **array;
|
||||
gchar **array;
|
||||
GString *v = NULL;
|
||||
|
||||
n_elements = sc->vptr->list_length (sc, vector);
|
||||
|
||||
array = g_new0 (gchar *, n_elements + 1);
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (j = 0; j < n_elements; j++)
|
||||
{
|
||||
|
@ -888,10 +924,18 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
"Item %d in vector is not a string (argument %d for function %s)",
|
||||
j+1, arg_index+1, proc_name);
|
||||
g_strfreev (array);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return foreign_error (sc, error_str, vector);
|
||||
}
|
||||
|
||||
array[j] = g_strdup (sc->vptr->string_value (v_element));
|
||||
if (v)
|
||||
{
|
||||
gchar *escaped = g_strescape (array[j], NULL);
|
||||
g_string_append_printf (v, "%s\"%s\"", j == 0 ? "" : " ", escaped);
|
||||
g_free (escaped);
|
||||
}
|
||||
|
||||
vector = sc->vptr->pair_cdr (vector);
|
||||
}
|
||||
|
@ -911,6 +955,12 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("#(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_DISPLAY (value))
|
||||
|
@ -921,10 +971,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpDisplay *display =
|
||||
gimp_display_get_by_id (sc->vptr->ivalue (arg_val));
|
||||
GimpDisplay *display;
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
display = gimp_display_get_by_id (id);
|
||||
|
||||
g_value_set_object (value, display);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_IMAGE (value))
|
||||
|
@ -935,10 +990,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpImage *image =
|
||||
gimp_image_get_by_id (sc->vptr->ivalue (arg_val));
|
||||
GimpImage *image;
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
image = gimp_image_get_by_id (id);
|
||||
|
||||
g_value_set_object (value, image);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_LAYER (value))
|
||||
|
@ -949,10 +1009,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpLayer *layer =
|
||||
gimp_layer_get_by_id (sc->vptr->ivalue (arg_val));
|
||||
GimpLayer *layer;
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
layer = gimp_layer_get_by_id (id);
|
||||
|
||||
g_value_set_object (value, layer);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_LAYER_MASK (value))
|
||||
|
@ -963,10 +1028,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpLayerMask *layer_mask =
|
||||
gimp_layer_mask_get_by_id (sc->vptr->ivalue (arg_val));
|
||||
GimpLayerMask *layer_mask;
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
layer_mask = gimp_layer_mask_get_by_id (id);
|
||||
|
||||
g_value_set_object (value, layer_mask);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_CHANNEL (value))
|
||||
|
@ -977,10 +1047,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpChannel *channel =
|
||||
gimp_channel_get_by_id (sc->vptr->ivalue (arg_val));
|
||||
GimpChannel *channel;
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
channel = gimp_channel_get_by_id (id);
|
||||
|
||||
g_value_set_object (value, channel);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_DRAWABLE (value))
|
||||
|
@ -996,6 +1071,9 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
pointer error = marshal_ID_to_item (sc, a, id, value);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_PATH (value))
|
||||
|
@ -1006,10 +1084,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpPath *path =
|
||||
gimp_path_get_by_id (sc->vptr->ivalue (arg_val));
|
||||
GimpPath *path;
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
path = gimp_path_get_by_id (id);
|
||||
|
||||
g_value_set_object (value, path);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_ITEM (value))
|
||||
|
@ -1020,12 +1103,11 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
gint item_ID;
|
||||
item_ID = sc->vptr->ivalue (arg_val);
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
if (gimp_item_id_is_valid (item_ID))
|
||||
if (gimp_item_id_is_valid (id))
|
||||
{
|
||||
GimpItem *item = gimp_item_get_by_id (item_ID);
|
||||
GimpItem *item = gimp_item_get_by_id (id);
|
||||
g_value_set_object (value, item);
|
||||
}
|
||||
else
|
||||
|
@ -1035,6 +1117,9 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
*/
|
||||
g_value_set_object (value, NULL);
|
||||
}
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_DRAWABLE_FILTER (value))
|
||||
|
@ -1045,9 +1130,7 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
gint id;
|
||||
|
||||
id = sc->vptr->ivalue (arg_val);
|
||||
gint id = sc->vptr->ivalue (arg_val);
|
||||
|
||||
if (gimp_drawable_filter_id_is_valid (id))
|
||||
{
|
||||
|
@ -1062,6 +1145,9 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
*/
|
||||
g_value_set_object (value, NULL);
|
||||
}
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_INT32_ARRAY (value))
|
||||
|
@ -1092,11 +1178,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
* FUTURE: List must be *exactly* n_elements long.
|
||||
* n_elements != sc->vptr->list_length (sc, vector))
|
||||
*/
|
||||
gint32 *array;
|
||||
gint32 *array;
|
||||
GString *v = NULL;
|
||||
|
||||
n_elements = sc->vptr->vector_length (vector);
|
||||
array = g_new0 (gint32, n_elements);
|
||||
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (j = 0; j < n_elements; j++)
|
||||
{
|
||||
pointer v_element = sc->vptr->vector_elem (vector, j);
|
||||
|
@ -1105,13 +1195,22 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
if (! sc->vptr->is_number (v_element))
|
||||
{
|
||||
g_free (array);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return script_type_error_in_container (sc, "numeric", arg_index, j, proc_name, vector);
|
||||
}
|
||||
|
||||
array[j] = (gint32) sc->vptr->ivalue (v_element);
|
||||
if (v)
|
||||
g_string_append_printf (v, "%s%d", j == 0 ? "" : " ", array[j]);
|
||||
}
|
||||
|
||||
gimp_value_take_int32_array (value, array, n_elements);
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("#(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
|
||||
debug_vector (sc, vector, "%ld");
|
||||
}
|
||||
|
@ -1125,11 +1224,14 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
}
|
||||
else
|
||||
{
|
||||
guint8 *array;
|
||||
guint8 *array;
|
||||
GString *v = NULL;
|
||||
|
||||
n_elements = sc->vptr->vector_length (vector);
|
||||
|
||||
array = g_new0 (guint8, n_elements);
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (j = 0; j < n_elements; j++)
|
||||
{
|
||||
|
@ -1138,13 +1240,22 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
if (!sc->vptr->is_number (v_element))
|
||||
{
|
||||
g_free (array);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return script_type_error_in_container (sc, "numeric", arg_index, j, proc_name, vector);
|
||||
}
|
||||
|
||||
array[j] = (guint8) sc->vptr->ivalue (v_element);
|
||||
if (v)
|
||||
g_string_append_printf (v, "%s%d", j == 0 ? "" : " ", array[j]);
|
||||
}
|
||||
|
||||
g_value_take_boxed (value, g_bytes_new_take (array, n_elements));
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("#(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
|
||||
debug_vector (sc, vector, "%ld");
|
||||
}
|
||||
|
@ -1159,9 +1270,12 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
else
|
||||
{
|
||||
gdouble *array;
|
||||
GString *v = NULL;
|
||||
|
||||
n_elements = sc->vptr->vector_length (vector);
|
||||
array = g_new0 (gdouble, n_elements);
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (j = 0; j < n_elements; j++)
|
||||
{
|
||||
|
@ -1170,13 +1284,22 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
if (!sc->vptr->is_number (v_element))
|
||||
{
|
||||
g_free (array);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return script_type_error_in_container (sc, "numeric", arg_index, j, proc_name, vector);
|
||||
}
|
||||
|
||||
array[j] = (gdouble) sc->vptr->rvalue (v_element);
|
||||
if (v)
|
||||
g_string_append_printf (v, "%s%f", j == 0 ? "" : " ", array[j]);
|
||||
}
|
||||
|
||||
gimp_value_take_double_array (value, array, n_elements);
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("#(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
|
||||
debug_vector (sc, vector, "%f");
|
||||
}
|
||||
|
@ -1191,12 +1314,15 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
|
||||
if (! (color = sf_color_get_color_from_name (color_string)))
|
||||
return script_type_error (sc, "color string", arg_index, proc_name);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("\"%s\"", color_string);
|
||||
}
|
||||
else if (sc->vptr->is_list (sc, arg_val))
|
||||
{
|
||||
pointer color_list = arg_val;
|
||||
|
||||
if (! (color = marshal_component_list_to_color (sc, color_list)))
|
||||
if (! (color = marshal_component_list_to_color (sc, color_list, strvalue)))
|
||||
return script_type_error (sc, "color list of numeric components", arg_index, proc_name);
|
||||
}
|
||||
else
|
||||
|
@ -1217,10 +1343,13 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
else
|
||||
{
|
||||
GeglColor **colors;
|
||||
GString *v = NULL;
|
||||
|
||||
n_elements = sc->vptr->vector_length (vector);
|
||||
|
||||
colors = g_new0 (GeglColor *, n_elements + 1);
|
||||
if (strvalue)
|
||||
v = g_string_new ("");
|
||||
|
||||
for (j = 0; j < n_elements; j++)
|
||||
{
|
||||
|
@ -1238,6 +1367,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
"Item %d in vector is not a color "
|
||||
"(argument %d for function %s)",
|
||||
j+1, arg_index+1, proc_name);
|
||||
if (v)
|
||||
g_string_free (v, TRUE);
|
||||
return script_error (sc, error_str, 0);
|
||||
}
|
||||
|
||||
|
@ -1253,9 +1384,16 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
|
||||
colors[j] = gegl_color_new (NULL);
|
||||
gegl_color_set_pixel (colors[j], babl_format ("R'G'B' u8"), rgb);
|
||||
if (v)
|
||||
g_string_append_printf (v, " '(%d %d %d)", rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
g_value_take_boxed (value, colors);
|
||||
if (v)
|
||||
{
|
||||
*strvalue = g_strdup_printf ("#(%s)", v->str);
|
||||
g_string_free (v, TRUE);
|
||||
}
|
||||
|
||||
g_debug ("color vector has %ld elements", sc->vptr->vector_length (vector));
|
||||
}
|
||||
|
@ -1306,6 +1444,16 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
g_debug ("data '%s'", (char *)parasite.data);
|
||||
|
||||
g_value_set_boxed (value, ¶site);
|
||||
if (strvalue)
|
||||
{
|
||||
gchar *escaped_name = g_strescape (parasite.name, NULL);
|
||||
gchar *escaped_data = g_strescape (parasite.data, NULL);
|
||||
|
||||
*strvalue = g_strdup_printf ("(\"%s\" %d \"%s\")",
|
||||
escaped_name, parasite.flags, escaped_data);
|
||||
g_free (escaped_name);
|
||||
g_free (escaped_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_CORE_OBJECT_ARRAY (value))
|
||||
|
@ -1318,7 +1466,7 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
|
||||
if (sc->vptr->is_vector (vector))
|
||||
{
|
||||
pointer error = marshal_vector_to_item_array (sc, vector, value);
|
||||
pointer error = marshal_vector_to_item_array (sc, vector, value, strvalue);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
@ -1332,6 +1480,9 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
if (! sc->vptr->is_string (arg_val))
|
||||
return script_type_error (sc, "string for path", arg_index, proc_name);
|
||||
marshal_path_string_to_gfile (sc, a, value);
|
||||
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%s", sc->vptr->string_value (arg_val));
|
||||
}
|
||||
else if (G_VALUE_TYPE (value) == GIMP_TYPE_PDB_STATUS_TYPE)
|
||||
{
|
||||
|
@ -1369,6 +1520,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
return script_error (sc, "runtime: resource ID of improper subclass.", a);
|
||||
}
|
||||
g_value_set_object (value, resource);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", resource_id);
|
||||
}
|
||||
}
|
||||
else if (GIMP_VALUE_HOLDS_EXPORT_OPTIONS (value))
|
||||
|
@ -1384,6 +1537,8 @@ script_fu_marshal_arg_to_value (scheme *sc,
|
|||
* create a GimpExportOptions (actually a proxy?)
|
||||
*/
|
||||
g_value_set_object (value, NULL);
|
||||
if (strvalue)
|
||||
*strvalue = g_strdup_printf ("%d", -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1455,6 +1610,8 @@ script_fu_marshal_procedure_call (scheme *sc,
|
|||
arg_specs = gimp_procedure_get_arguments (procedure, &n_arg_specs);
|
||||
actual_arg_count = sc->vptr->list_length (sc, a) - 1;
|
||||
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
/* Check the supplied number of arguments.
|
||||
* This only gives messages to the console.
|
||||
* It does not ensure that the count of supplied args equals the count of formal args.
|
||||
|
@ -1466,67 +1623,149 @@ script_fu_marshal_procedure_call (scheme *sc,
|
|||
* Extra supplied args can be discarded.
|
||||
* Formerly, this was a deprecated behavior depending on "permissive".
|
||||
*/
|
||||
{
|
||||
if (actual_arg_count > n_arg_specs)
|
||||
{
|
||||
/* Permit extra args. Will discard args from script, to next right paren.*/
|
||||
g_info ("in script, permitting too many args to %s", proc_name);
|
||||
}
|
||||
else if (actual_arg_count < n_arg_specs)
|
||||
{
|
||||
/* Permit too few args. The config carries a sane default for most types. */
|
||||
g_info ("in script, permitting too few args to %s", proc_name);
|
||||
}
|
||||
/* else equal counts of args. */
|
||||
}
|
||||
if (gimp_procedure_is_core (procedure))
|
||||
{
|
||||
if (actual_arg_count > n_arg_specs)
|
||||
{
|
||||
/* Permit extra args. Will discard args from script, to next right paren.*/
|
||||
g_info ("in script, permitting too many args to %s", proc_name);
|
||||
}
|
||||
else if (actual_arg_count < n_arg_specs)
|
||||
{
|
||||
/* Permit too few args. The config carries a sane default for most types. */
|
||||
g_info ("in script, permitting too few args to %s", proc_name);
|
||||
}
|
||||
/* else equal counts of args. */
|
||||
}
|
||||
|
||||
/* Marshall the supplied arguments */
|
||||
for (i = 0; i < n_arg_specs; i++)
|
||||
if (gimp_procedure_is_core (procedure) ||
|
||||
! sc->vptr->is_arg_name (sc->vptr->pair_car (a)))
|
||||
{
|
||||
GParamSpec *arg_spec = arg_specs[i];
|
||||
GValue value = G_VALUE_INIT;
|
||||
GString *deprecation_warning = NULL;
|
||||
|
||||
consumed_arg_count++;
|
||||
|
||||
if (consumed_arg_count > actual_arg_count)
|
||||
if (! gimp_procedure_is_core (procedure))
|
||||
{
|
||||
/* Exhausted supplied arguments before formal specs. */
|
||||
|
||||
/* Say formal type of first missing arg. */
|
||||
g_warning ("Missing arg type: %s", g_type_name (G_PARAM_SPEC_VALUE_TYPE (arg_spec)));
|
||||
|
||||
/* Break loop over formal specs. Continuation is to call PDB with partial args. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
a = sc->vptr->pair_cdr (a); /* advance pointer to next arg in list. */
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (arg_spec));
|
||||
|
||||
debug_in_arg (sc, a, i, g_type_name (G_VALUE_TYPE (&value)));
|
||||
|
||||
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, i, arg_spec, &value);
|
||||
|
||||
if (return_val != sc->NIL)
|
||||
{
|
||||
g_value_unset (&value);
|
||||
return return_val;
|
||||
deprecation_warning = g_string_new ("Calling Plug-In PDB procedures with arguments as an ordered list is deprecated.\n"
|
||||
"Please use named arguments: (");
|
||||
g_string_append (deprecation_warning, proc_name);
|
||||
}
|
||||
|
||||
debug_gvalue (&value);
|
||||
if (g_param_value_validate (arg_spec, &value))
|
||||
for (i = 0; i < n_arg_specs; i++)
|
||||
{
|
||||
gchar error_message[1024];
|
||||
GParamSpec *arg_spec = arg_specs[i];
|
||||
GValue value = G_VALUE_INIT;
|
||||
gchar *strvalue = NULL;
|
||||
|
||||
g_snprintf (error_message, sizeof (error_message),
|
||||
"Invalid value for argument %d",
|
||||
i);
|
||||
consumed_arg_count++;
|
||||
|
||||
if (consumed_arg_count > actual_arg_count)
|
||||
{
|
||||
/* Exhausted supplied arguments before formal specs. */
|
||||
|
||||
/* Say formal type of first missing arg. */
|
||||
g_warning ("Missing arg type: %s", g_type_name (G_PARAM_SPEC_VALUE_TYPE (arg_spec)));
|
||||
|
||||
/* Break loop over formal specs. Continuation is to call PDB with partial args. */
|
||||
break;
|
||||
}
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (arg_spec));
|
||||
|
||||
debug_in_arg (sc, a, i, g_type_name (G_VALUE_TYPE (&value)));
|
||||
|
||||
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, i, arg_spec, &value, &strvalue);
|
||||
|
||||
if (return_val != sc->NIL)
|
||||
{
|
||||
g_value_unset (&value);
|
||||
return return_val;
|
||||
}
|
||||
|
||||
debug_gvalue (&value);
|
||||
if (g_param_value_validate (arg_spec, &value))
|
||||
{
|
||||
gchar error_message[1024];
|
||||
|
||||
g_snprintf (error_message, sizeof (error_message),
|
||||
"Invalid value for argument %d",
|
||||
i);
|
||||
g_value_unset (&value);
|
||||
|
||||
return script_error (sc, error_message, 0);
|
||||
}
|
||||
g_object_set_property (G_OBJECT (config), arg_specs[i]->name, &value);
|
||||
g_value_unset (&value);
|
||||
|
||||
return script_error (sc, error_message, 0);
|
||||
if (deprecation_warning != NULL)
|
||||
g_string_append_printf (deprecation_warning, " #:%s %s",
|
||||
arg_specs[i]->name, strvalue);
|
||||
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
g_free (strvalue);
|
||||
}
|
||||
if (deprecation_warning != NULL)
|
||||
{
|
||||
g_string_append (deprecation_warning, ")");
|
||||
g_warning ("%s", deprecation_warning->str);
|
||||
|
||||
g_string_free (deprecation_warning, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < actual_arg_count; i++)
|
||||
{
|
||||
GParamSpec *arg_spec;
|
||||
gchar *arg_name;
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
if (! sc->vptr->is_arg_name (sc->vptr->pair_car (a)))
|
||||
{
|
||||
g_snprintf (error_str, sizeof (error_str),
|
||||
"Expected argument name for argument %d", i);
|
||||
return script_error (sc, error_str, 0);
|
||||
}
|
||||
|
||||
arg_name = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
|
||||
arg_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), arg_name);
|
||||
if (arg_spec == NULL)
|
||||
{
|
||||
g_snprintf (error_str, sizeof (error_str),
|
||||
"Invalid argument name: %s", arg_name);
|
||||
g_free (arg_name);
|
||||
return script_error (sc, error_str, 0);
|
||||
}
|
||||
|
||||
if (i == actual_arg_count - 1)
|
||||
{
|
||||
g_snprintf (error_str, sizeof (error_str),
|
||||
"Lonely argument with no value: %s", arg_name);
|
||||
g_free (arg_name);
|
||||
return script_error (sc, error_str, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
i++;
|
||||
}
|
||||
|
||||
g_value_init (&value, arg_spec->value_type);
|
||||
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, i, arg_spec, &value, NULL);
|
||||
if (return_val != sc->NIL)
|
||||
{
|
||||
g_value_unset (&value);
|
||||
g_free (arg_name);
|
||||
return return_val;
|
||||
}
|
||||
|
||||
g_object_set_property (G_OBJECT (config), arg_name, &value);
|
||||
g_value_unset (&value);
|
||||
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
g_object_set_property (G_OBJECT (config), arg_specs[i]->name, &value);
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
/* Omit refresh scripts from a script, better than crashing, see #575830. */
|
||||
|
@ -1650,7 +1889,7 @@ script_fu_marshal_drawable_filter_configure (scheme *sc,
|
|||
g_value_init (&value, arg_spec->value_type);
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, arg_index, arg_spec, &value);
|
||||
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, arg_index, arg_spec, &value, NULL);
|
||||
|
||||
if (return_val != sc->NIL)
|
||||
{
|
||||
|
|
|
@ -269,7 +269,7 @@ script_fu_parse_default_spec (scheme *sc,
|
|||
else if (sc->vptr->is_list (sc, default_spec))
|
||||
{
|
||||
/* default_spec is list of numbers. */
|
||||
GeglColor *color = marshal_component_list_to_color (sc, default_spec);
|
||||
GeglColor *color = marshal_component_list_to_color (sc, default_spec, NULL);
|
||||
|
||||
if (color == NULL)
|
||||
{
|
||||
|
|
|
@ -116,6 +116,7 @@ ts_get_error_string (scheme *sc)
|
|||
#define TOK_SHARP_CONST 11
|
||||
#define TOK_VEC 12
|
||||
#define TOK_USCORE 13
|
||||
#define TOK_ARG 14
|
||||
|
||||
#define BACKQUOTE '`'
|
||||
#define DELIMITERS "()\";\f\t\v\n\r "
|
||||
|
@ -198,7 +199,8 @@ enum scheme_types {
|
|||
T_PROMISE=13,
|
||||
T_ENVIRONMENT=14,
|
||||
T_BYTE=15,
|
||||
T_LAST_SYSTEM_TYPE=15
|
||||
T_ARG_SLOT=16,
|
||||
T_LAST_SYSTEM_TYPE=16
|
||||
};
|
||||
|
||||
/* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
|
||||
|
@ -241,6 +243,7 @@ static num num_one;
|
|||
#define type(p) (typeflag(p)&T_MASKTYPE)
|
||||
|
||||
INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); }
|
||||
INTERFACE INLINE int is_arg_name(pointer p) { return (type(p)==T_ARG_SLOT); }
|
||||
#define strvalue(p) ((p)->_object._string._svalue)
|
||||
#define strlength(p) ((p)->_object._string._length)
|
||||
|
||||
|
@ -442,6 +445,7 @@ static gunichar inchar(scheme *sc);
|
|||
static void backchar(scheme *sc, gunichar c);
|
||||
static char *readstr_upto(scheme *sc, char *delim);
|
||||
static pointer readstrexp(scheme *sc);
|
||||
static pointer read_arg_name_exp(scheme *sc);
|
||||
static INLINE int skipspace(scheme *sc);
|
||||
static int token(scheme *sc);
|
||||
static void printslashstring(scheme *sc, char *s, int len);
|
||||
|
@ -1159,6 +1163,21 @@ INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
|
|||
return (x);
|
||||
}
|
||||
|
||||
INTERFACE pointer
|
||||
mk_arg_name (scheme *sc,
|
||||
const char *str)
|
||||
{
|
||||
gint len = strlen (str);
|
||||
|
||||
pointer x = get_cell (sc, sc->NIL, sc->NIL);
|
||||
|
||||
typeflag(x) = (T_ARG_SLOT | T_ATOM);
|
||||
strvalue(x) = store_string (sc, len, str, 0);
|
||||
strlength(x) = len;
|
||||
|
||||
return (x);
|
||||
}
|
||||
|
||||
/* len is the length for the empty string in characters */
|
||||
INTERFACE pointer mk_empty_string(scheme *sc, int len, gunichar fill) {
|
||||
pointer x = get_cell(sc, sc->NIL, sc->NIL);
|
||||
|
@ -1989,6 +2008,35 @@ static pointer readstrexp(scheme *sc) {
|
|||
}
|
||||
}
|
||||
|
||||
static pointer
|
||||
read_arg_name_exp (scheme *sc)
|
||||
{
|
||||
char *p = sc->strbuff;
|
||||
gunichar c;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
c = inchar (sc);
|
||||
if (c == EOF || p - sc->strbuff > sizeof (sc->strbuff) - 1)
|
||||
{
|
||||
*p = 0;
|
||||
return sc->F;
|
||||
}
|
||||
else if (g_unichar_isspace (c))
|
||||
{
|
||||
*p = 0;
|
||||
return mk_arg_name (sc, sc->strbuff);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint len;
|
||||
|
||||
len = g_unichar_to_utf8 (c, p);
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check c is in chars */
|
||||
static INLINE int is_one_of(char *s, gunichar c) {
|
||||
if (c==EOF)
|
||||
|
@ -2097,6 +2145,8 @@ static int token(scheme *sc) {
|
|||
{ return (TOK_EOF); }
|
||||
else
|
||||
{ return (token(sc));}
|
||||
} else if (c == ':') {
|
||||
return (TOK_ARG);
|
||||
} else {
|
||||
backchar(sc,c);
|
||||
if(is_one_of(" tfodxb\\",c)) {
|
||||
|
@ -4649,6 +4699,14 @@ static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
|
|||
} else {
|
||||
s_return(sc,x);
|
||||
}
|
||||
case TOK_ARG: {
|
||||
x = read_arg_name_exp(sc);
|
||||
if (x == sc->F) {
|
||||
Error_0 (sc, "Error reading argument slot name");
|
||||
}
|
||||
setimmutable(x);
|
||||
s_return(sc,x);
|
||||
}
|
||||
case TOK_RPAREN:
|
||||
Error_1 (sc, "syntax error: unexpected right parenthesis", 0);
|
||||
case TOK_DOT:
|
||||
|
@ -5097,6 +5155,7 @@ static struct scheme_interface vtbl ={
|
|||
mk_vector,
|
||||
mk_foreign_func,
|
||||
mk_closure,
|
||||
mk_arg_name,
|
||||
putstr,
|
||||
putcharacter,
|
||||
|
||||
|
@ -5145,6 +5204,8 @@ static struct scheme_interface vtbl ={
|
|||
is_immutable,
|
||||
setimmutable,
|
||||
|
||||
is_arg_name,
|
||||
|
||||
scheme_load_file,
|
||||
scheme_load_string
|
||||
};
|
||||
|
|
|
@ -200,6 +200,7 @@ struct scheme_interface {
|
|||
pointer (*mk_vector)(scheme *sc, int len);
|
||||
pointer (*mk_foreign_func)(scheme *sc, foreign_func f);
|
||||
pointer (*mk_closure)(scheme *sc, pointer c, pointer e);
|
||||
pointer (*mk_arg_name)(scheme *sc, const char *str);
|
||||
void (*putstr)(scheme *sc, const char *s);
|
||||
void (*putcharacter)(scheme *sc, gunichar c);
|
||||
|
||||
|
@ -250,6 +251,8 @@ struct scheme_interface {
|
|||
int (*is_immutable)(pointer p);
|
||||
void (*setimmutable)(pointer p);
|
||||
|
||||
int (*is_arg_name)(pointer p);
|
||||
|
||||
void (*load_file)(scheme *sc, FILE *fin);
|
||||
void (*load_string)(scheme *sc, const char *input);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue