From 6cb6d2289bdab4233e61bab83a4d14f3c01d40fb Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 16 May 2011 17:10:08 +0100 Subject: [PATCH] new CLI done the new cli interface is done, try "vips add a.jpg b.jpg out.jpg", or "vips add". --- ChangeLog | 1 + TODO | 6 -- libvips/arithmetic/arithmetic.c | 4 + libvips/fred# | 42 +++++++++++ libvips/include/vips/error.h | 1 + libvips/include/vips/object.h | 6 ++ libvips/include/vips/operation.h | 2 +- libvips/iofuncs/error.c | 21 ++++++ libvips/iofuncs/object.c | 36 +++++---- libvips/iofuncs/operation.c | 123 ++++++++++++++++++++----------- tools/vips.c | 113 ++++++++++++++-------------- 11 files changed, 237 insertions(+), 118 deletions(-) create mode 100644 libvips/fred# diff --git a/ChangeLog b/ChangeLog index 3b48c49d..ad329a04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -56,6 +56,7 @@ - added vips_image_get_data() - updated German translation (thanks Chris) - fixed typo in im_conv() overflow estimation which could cause errors +- vips.c has new action syntax, knows about vips8 operations 30/11/10 started 7.24.0 - bump for new stable diff --git a/TODO b/TODO index 0fa351f5..395b14d9 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,6 @@ - we seem to have code shared between object and operation: vips_object_set_arg() and vips_object_set_required_test(), common this up - currently adding stuff to operation.c to set args from strings, with extra - logic for things like create image from filename ... useful for object.c - as well? - - test booltest and imtest flags - diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index ee40229f..22fe3538 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -71,7 +71,9 @@ G_DEFINE_ABSTRACT_TYPE( VipsArithmetic, vips_arithmetic, VIPS_TYPE_OPERATION ); static int vips_arithmetic_build( VipsObject *object ) { +#ifdef DEBUG VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object ); +#endif /*DEBUG*/ if( VIPS_OBJECT_CLASS( vips_arithmetic_parent_class )->build( object ) ) return( -1 ); @@ -82,10 +84,12 @@ vips_arithmetic_build( VipsObject *object ) * At the moment we _generate() in binary.c and unary.c. */ +#ifdef DEBUG printf( "vips_arithmetic_build: booltest = %d\n", arithmetic->booltest ); printf( "vips_arithmetic_build: imtest = %p\n", arithmetic->imtest ); +#endif /*DEBUG*/ return( 0 ); } diff --git a/libvips/fred# b/libvips/fred# new file mode 100644 index 00000000..9d733a6f --- /dev/null +++ b/libvips/fred# @@ -0,0 +1,42 @@ +Making install in include +make[1]: Entering directory `/home/john/GIT/libvips/libvips/include' +Making install in vips +make[2]: Entering directory `/home/john/GIT/libvips/libvips/include/vips' +glib-mkenums --template enumtemplate \ + ../../../libvips/include/vips/memory.h ../../../libvips/include/vips/util.h ../../../libvips/include/vips/buf.h ../../../libvips/include/vips/image.h ../../../libvips/include/vips/object.h > xgen-geth && \ + ( cmp -s xgen-geth enumtypes.h || cp xgen-geth enumtypes.h ) && \ + rm -f xgen-geth +make[3]: Entering directory `/home/john/GIT/libvips/libvips/include/vips' +make[3]: Nothing to be done for `install-exec-am'. +glib-mkenums --template enumtemplate \ + ../../../libvips/include/vips/memory.h ../../../libvips/include/vips/util.h ../../../libvips/include/vips/buf.h ../../../libvips/include/vips/image.h ../../../libvips/include/vips/object.h > xgen-geth && \ + ( cmp -s xgen-geth enumtypes.h || cp xgen-geth enumtypes.h ) && \ + rm -f xgen-geth +test -z "/home/john/vips/include/vips" || /bin/mkdir -p "/home/john/vips/include/vips" + /usr/bin/install -c -m 644 almostdeprecated.h deprecated.h arithmetic.h boolean.h buf.h colour.h conversion.h convolution.h debug.h dispatch.h disp.h enumtypes.h error.h operation.h format.h inplace.h generate.h header.h histograms_lut.h freq_filt.h image.h interpolate.h intl.h mask.h memory.h morphology.h mosaicing.h other.h video.h cimg_funcs.h object.h private.h rect.h region.h relational.h resample.h semaphore.h threadpool.h thread.h transform.h '/home/john/vips/include/vips' + /usr/bin/install -c -m 644 util.h version.h vector.h vips7compat.h vips.h '/home/john/vips/include/vips' +make[3]: Leaving directory `/home/john/GIT/libvips/libvips/include/vips' +make[2]: Leaving directory `/home/john/GIT/libvips/libvips/include/vips' +make[2]: Entering directory `/home/john/GIT/libvips/libvips/include' +make[3]: Entering directory `/home/john/GIT/libvips/libvips/include' +make[3]: Nothing to be done for `install-exec-am'. +make[3]: Nothing to be done for `install-data-am'. +make[3]: Leaving directory `/home/john/GIT/libvips/libvips/include' +make[2]: Leaving directory `/home/john/GIT/libvips/libvips/include' +make[1]: Leaving directory `/home/john/GIT/libvips/libvips/include' +Making install in arithmetic +make[1]: Entering directory `/home/john/GIT/libvips/libvips/arithmetic' +/bin/bash ../../libtool --tag=CC --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT arith_dispatch.lo -MD -MP -MF .deps/arith_dispatch.Tpo -c -o arith_dispatch.lo arith_dispatch.c +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT arith_dispatch.lo -MD -MP -MF .deps/arith_dispatch.Tpo -c arith_dispatch.c -fPIC -DPIC -o .libs/arith_dispatch.o +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT arith_dispatch.lo -MD -MP -MF .deps/arith_dispatch.Tpo -c arith_dispatch.c -o arith_dispatch.o >/dev/null 2>&1 +mv -f .deps/arith_dispatch.Tpo .deps/arith_dispatch.Plo +/bin/bash ../../libtool --tag=CC --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_abs.lo -MD -MP -MF .deps/im_abs.Tpo -c -o im_abs.lo im_abs.c +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_abs.lo -MD -MP -MF .deps/im_abs.Tpo -c im_abs.c -fPIC -DPIC -o .libs/im_abs.o +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_abs.lo -MD -MP -MF .deps/im_abs.Tpo -c im_abs.c -o im_abs.o >/dev/null 2>&1 +mv -f .deps/im_abs.Tpo .deps/im_abs.Plo +/bin/bash ../../libtool --tag=CC --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_avg.lo -MD -MP -MF .deps/im_avg.Tpo -c -o im_avg.lo im_avg.c +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_avg.lo -MD -MP -MF .deps/im_avg.Tpo -c im_avg.c -fPIC -DPIC -o .libs/im_avg.o +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_avg.lo -MD -MP -MF .deps/im_avg.Tpo -c im_avg.c -o im_avg.o >/dev/null 2>&1 +mv -f .deps/im_avg.Tpo .deps/im_avg.Plo +/bin/bash ../../libtool --tag=CC --mode=compile gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_bandmean.lo -MD -MP -MF .deps/im_bandmean.Tpo -c -o im_bandmean.lo im_bandmean.c +libtool: compile: gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I../.. -I../../libvips/include -DDEBUG_FATAL -DDEBUG_LEAK -pthread -fopenmp -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/libxml2 -I/usr/include/libpng12 -I/usr/include/libexif -I/usr/include/glib-2.0 -I/usr/include/freetype2 -I/usr/include/OpenEXR -I/usr/include/ImageMagick -I/home/john/vips/include/orc-0.4 -g -Wall -MT im_bandmean.lo -MD -MP -MF .deps/im_bandmean.Tpo -c im_bandmean.c -fPIC -DPIC -o .libs/im_bandmean.o diff --git a/libvips/include/vips/error.h b/libvips/include/vips/error.h index d525c977..47155e58 100644 --- a/libvips/include/vips/error.h +++ b/libvips/include/vips/error.h @@ -44,6 +44,7 @@ void vips_error_system( int err, const char *domain, const char *fmt, ... ) __attribute__((format(printf, 3, 4))); void vips_verror_system( int err, const char *domain, const char *fmt, va_list ap ); +void vips_error_g( GError **error ); void vips_warn( const char *domain, const char *fmt, ... ) __attribute__((format(printf, 2, 3))); void vips_vwarn( const char *domain, const char *fmt, va_list ap ); diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index 09a00944..eff61483 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -168,6 +168,12 @@ typedef void *(*VipsArgumentMapFn)( VipsObject *, GParamSpec *, void *vips_argument_map( VipsObject *object, VipsArgumentMapFn fn, void *a, void *b ); +void *vips_argument_is_required( VipsObject *object, + GParamSpec *pspec, + VipsArgumentClass *argument_class, + VipsArgumentInstance *argument_instance, + void *a, void *b ); + #define VIPS_TYPE_OBJECT (vips_object_get_type()) #define VIPS_OBJECT( obj ) \ (G_TYPE_CHECK_INSTANCE_CAST( (obj), VIPS_TYPE_OBJECT, VipsObject )) diff --git a/libvips/include/vips/operation.h b/libvips/include/vips/operation.h index 62801c40..d3d502e9 100644 --- a/libvips/include/vips/operation.h +++ b/libvips/include/vips/operation.h @@ -68,7 +68,7 @@ VipsOperation *vips_operation_new( const char *name ); int vips_call( const char *operation_name, ... ); int vips_call_split( const char *operation_name, va_list optional, ... ); -GOptionGroup *vips_call_options( VipsOperation *operation ); +void vips_call_options( GOptionGroup *group, VipsOperation *operation ); int vips_call_argv( VipsOperation *operation, int argc, char **argv ); #ifdef __cplusplus diff --git a/libvips/iofuncs/error.c b/libvips/iofuncs/error.c index 73e376f0..1e360da3 100644 --- a/libvips/iofuncs/error.c +++ b/libvips/iofuncs/error.c @@ -249,6 +249,27 @@ vips_error_system( int err, const char *domain, const char *fmt, ... ) va_end( ap ); } +/** + * vips_error_g: + * @error: glib error pointer + * + * This function sets the glib error pointer from the vips error buffer and + * clears it. It's handy for returning errors to glib functions from vips. + * + * See also: g_set_error(). + */ +void +vips_error_g( GError **error ) +{ + static GQuark vips_domain = 0; + + if( !vips_domain ) + vips_domain = g_quark_from_string( "libvips" ); + + g_set_error( error, vips_domain, -1, "%s", vips_error_buffer() ); + vips_error_clear(); +} + /** * vips_error_clear: * diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index c5c59484..76121dfa 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -269,6 +269,23 @@ vips_argument_map( VipsObject *object, return( NULL ); } +/* Handy for vips_argument_map: look for a required arg. + */ +void * +vips_argument_is_required( VipsObject *object, + GParamSpec *pspec, + VipsArgumentClass *argument_class, + VipsArgumentInstance *argument_instance, + void *a, void *b ) +{ + if( (argument_class->flags & VIPS_ARGUMENT_REQUIRED) && + (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && + !argument_instance->assigned ) + return( pspec ); + + return( NULL ); +} + static void * vips_argument_init2( VipsObject *object, GParamSpec *pspec, VipsArgumentClass *argument_class, @@ -1008,8 +1025,10 @@ vips_object_set_argument_from_string( VipsObject *object, VipsArgumentInstance *argument_instance; GValue gvalue = { 0 }; +#ifdef DEBUG printf( "vips_object_set_argument_from_string: %s = %s\n", name, value ); +#endif /*DEBUG*/ pspec = g_object_class_find_property( G_OBJECT_CLASS( class ), name ); if( !pspec ) { @@ -1076,21 +1095,6 @@ vips_object_set_argument_from_string( VipsObject *object, return( 0 ); } -static void * -vips_object_set_required_test( VipsObject *object, - GParamSpec *pspec, - VipsArgumentClass *argument_class, - VipsArgumentInstance *argument_instance, - void *a, void *b ) -{ - if( (argument_class->flags & VIPS_ARGUMENT_REQUIRED) && - (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && - !argument_instance->assigned ) - return( pspec ); - - return( NULL ); -} - /* Set the first unassigned required arg to the string. */ static int @@ -1099,7 +1103,7 @@ vips_object_set_required( VipsObject *object, const char *value ) GParamSpec *pspec; if( !(pspec = vips_argument_map( object, - vips_object_set_required_test, NULL, NULL )) ) { + vips_argument_is_required, NULL, NULL )) ) { vips_error( "VipsObject", _( "no unset required arguments for %s" ), value ); return( -1 ); diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index ae938002..633de53e 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -28,8 +28,8 @@ */ /* - */ #define VIPS_DEBUG + */ #ifdef HAVE_CONFIG_H #include @@ -81,12 +81,13 @@ vips_operation_print_arg( VipsObject *object, GParamSpec *pspec, if( print->oftype ) vips_buf_appendf( buf, " %s :: %s\n", - pspec->name, - g_type_name( pspec->value_type ) ); + g_param_spec_get_name( pspec ), + g_type_name( + G_PARAM_SPEC_VALUE_TYPE( pspec ) ) ); else { if( print->n > 0 ) vips_buf_appends( buf, ", " ); - vips_buf_appends( buf, pspec->name ); + vips_buf_appends( buf, g_param_spec_get_name( pspec ) ); } print->n += 1; @@ -104,7 +105,8 @@ vips_operation_call_argument( VipsObject *object, GParamSpec *pspec, VipsArgument *argument = (VipsArgument *) argument_class; printf( " %s: offset = %d ", - argument->pspec->name, argument_class->offset ); + g_param_spec_get_name( argument->pspec ), + argument_class->offset ); if( argument_class->flags & VIPS_ARGUMENT_REQUIRED ) printf ("required " ); if( argument_class->flags & VIPS_ARGUMENT_CONSTRUCT ) @@ -220,7 +222,7 @@ vips_operation_set_valist (VipsOperation * operation, * for this class. */ if (g_object_class_find_property (G_OBJECT_CLASS (class), - pspec->name) == pspec) + g_param_spec_get_name( pspec )) == pspec) { /* End of stuff copy-pasted from vips_argument_map(). @@ -246,13 +248,14 @@ vips_operation_set_valist (VipsOperation * operation, char *str; str = g_strdup_value_contents (&value); - VIPS_DEBUG_MSG ("\t%s = %s\n", pspec->name, str); + VIPS_DEBUG_MSG ("\t%s = %s\n", + g_param_spec_get_name( pspec ), str); g_free (str); } #endif /*VIPS_DEBUG */ g_object_set_property (G_OBJECT (operation), - pspec->name, &value); + g_param_spec_get_name( pspec ), &value); g_value_unset (&value); } } @@ -356,21 +359,6 @@ vips_call_split( const char *operation_name, va_list optional, ... ) return( result ); } -static void * -vips_object_set_required_test( VipsObject *object, - GParamSpec *pspec, - VipsArgumentClass *argument_class, - VipsArgumentInstance *argument_instance, - void *a, void *b ) -{ - if( (argument_class->flags & VIPS_ARGUMENT_REQUIRED) && - (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && - !argument_instance->assigned ) - return( pspec ); - - return( NULL ); -} - static int vips_call_argv_set_required( VipsOperation *operation, const char *value ) { @@ -379,31 +367,95 @@ vips_call_argv_set_required( VipsOperation *operation, const char *value ) /* Search for the first unset required argument. */ if( !(pspec = vips_argument_map( VIPS_OBJECT( operation ), - vips_object_set_required_test, NULL, NULL )) ) { + vips_argument_is_required, NULL, NULL )) ) { vips_error( "VipsOperation", _( "no unset required arguments for %s" ), value ); return( -1 ); } if( vips_object_set_argument_from_string( VIPS_OBJECT( operation ), - pspec->name, value ) ) + g_param_spec_get_name( pspec ), value ) ) return( -1 ); return( 0 ); } +static void * +vips_call_char_option( VipsObject *object, + GParamSpec *pspec, + VipsArgumentClass *argument_class, + VipsArgumentInstance *argument_instance, + void *a, void *b ) +{ + const char *name = (const char *) a; + const char *value = (const char *) b; + + if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) && + (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && + !argument_instance->assigned && + g_param_spec_get_name( pspec )[0] == name[0] ) + if( vips_object_set_argument_from_string( object, + g_param_spec_get_name( pspec ), value ) ) + return( object ); + + return( NULL ); +} + +static void * +vips_call_name_option( VipsObject *object, + GParamSpec *pspec, + VipsArgumentClass *argument_class, + VipsArgumentInstance *argument_instance, + void *a, void *b ) +{ + const char *name = (const char *) a; + const char *value = (const char *) b; + + if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) && + (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && + !argument_instance->assigned && + strcmp( g_param_spec_get_name( pspec ), name ) == 0 ) + if( vips_object_set_argument_from_string( object, + g_param_spec_get_name( pspec ), value ) ) + return( object ); + + return( NULL ); +} + static gboolean vips_call_options_set( const gchar *option_name, const gchar *value, gpointer data, GError **error ) { VipsOperation *operation = (VipsOperation *) data; + const char *name; VIPS_DEBUG_MSG( "vips_call_options_set: %s = %s\n", option_name, value ); - if( vips_object_set_argument_from_string( VIPS_OBJECT( operation ), - option_name, value ) ) - return( FALSE ); + /* Remove any leading "--" from the option name. + */ + for( name = option_name; *name == '-'; name++ ) + ; + + /* If this is a single-character name, find the first unset pspec with + * that initial. Otherwise, search for a spec of that nmae. + */ + if( strlen( name ) == 1 ) { + if( vips_argument_map( VIPS_OBJECT( operation ), + vips_call_char_option, + (void *) name, (void *) value ) ) { + vips_error_g( error ); + return( FALSE ); + } + } + else { + if( vips_argument_map( VIPS_OBJECT( operation ), + vips_call_name_option, + (void *) name, (void *) value ) ) { + vips_error_g( error ); + return( FALSE ); + } + } return( TRUE ); } @@ -442,22 +494,11 @@ vips_call_options_add( VipsObject *object, return( NULL ); } -GOptionGroup * -vips_call_options( VipsOperation *operation ) +void +vips_call_options( GOptionGroup *group, VipsOperation *operation ) { - VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( operation ); - GOptionGroup *group; - - group = g_option_group_new( object_class->nickname, - object_class->description, - _( "Show operation options" ), - operation, - NULL ); - (void) vips_argument_map( VIPS_OBJECT( operation ), vips_call_options_add, group, NULL ); - - return( group ); } /* Our main command-line entry point. Optional args should have been set by diff --git a/tools/vips.c b/tools/vips.c index b456198e..d9ace2bc 100644 --- a/tools/vips.c +++ b/tools/vips.c @@ -66,8 +66,8 @@ /* #define DEBUG_FATAL #define DEBUG_LEAK - */ #define DEBUG + */ /* Need to disable these sometimes. #undef DEBUG_FATAL @@ -99,7 +99,7 @@ static GOptionEntry main_option[] = { N_( "load PLUGIN" ), N_( "PLUGIN" ) }, { "version", 'v', 0, G_OPTION_ARG_NONE, &main_option_version, - N_( "print im_version_string" ), NULL }, + N_( "print version" ), NULL }, { NULL } }; @@ -962,6 +962,20 @@ parse_options( GOptionContext *context, int *argc, char **argv ) } } +static GOptionGroup * +add_main_group( GOptionContext *context, VipsOperation *user_data ) +{ + GOptionGroup *main_group; + + main_group = g_option_group_new( NULL, NULL, NULL, user_data, NULL ); + g_option_group_add_entries( main_group, main_option ); + g_option_group_set_translation_domain( main_group, GETTEXT_PACKAGE ); + g_option_context_set_main_group( context, main_group ); + g_option_context_add_group( context, im_get_option_group() ); + + return( main_group ); +} + /* VIPS universal main program. */ int @@ -969,9 +983,10 @@ main( int argc, char **argv ) { char *action; GOptionContext *context; + GOptionGroup *main_group; VipsOperation *operation; im_function *fn; - int i; + int i, j; gboolean handled; if( im_init_world( argv[0] ) ) @@ -996,69 +1011,61 @@ main( int argc, char **argv ) fprintf( stderr, "*** DEBUG_LEAK: will leak test on exit\n" ); #endif /*!DEBUG_LEAK*/ - /* We generate part of our g_options dynamically depending on the - * action, so we can't parse our args before getting the action. So - * therefore the action must always be the first argument. + /* Try to find our action. */ + action = NULL; /* Should we try to run the thing we are named as? */ - if( !im_isprefix( "vips", g_get_prgname() ) ) { + if( !im_isprefix( "vips", g_get_prgname() ) ) action = argv[0]; - argv += 1; - argc -= 1; - } - else { - action = argv[1]; - - /* "Just "vips" with no args. + if( !action ) { + /* Look for the first non-option argument, if any, and make + * that our action. */ - if( !action ) - return( 0 ); + for( i = 1; i < argc; i++ ) + if( argv[i][0] != '-' ) { + action = argv[i]; - argv += 2; - argc -= 2; + /* Remove the action from argv. + */ + for( j = i; j < argc; j++ ) + argv[j] = argv[j + 1]; + argc -= 1; + + break; + } } - context = g_option_context_new( _( "[ACTION] [OPTIONS] [PARAMETERS] - " "VIPS driver program" ) ); - - g_option_context_add_main_entries( context, - main_option, GETTEXT_PACKAGE ); - g_option_context_add_group( context, im_get_option_group() ); - handled = FALSE; - /* Could be one of our actions. + /* Could be one of our built-in actions. */ - for( i = 0; i < VIPS_NUMBER( actions ); i++ ) - if( strcmp( action, actions[i].name ) == 0 ) { - GOptionGroup *group; + if( action ) + for( i = 0; i < VIPS_NUMBER( actions ); i++ ) + if( strcmp( action, actions[i].name ) == 0 ) { + main_group = add_main_group( context, NULL ); + g_option_group_add_entries( main_group, + actions[i].group ); + parse_options( context, &argc, argv ); - group = g_option_group_new( actions[i].name, - "vips action", "show action options", - NULL, NULL ); - g_option_group_add_entries( group, - actions[i].group ); - g_option_context_add_group( context, group ); - parse_options( context, &argc, argv ); + if( actions[i].action( argc - 1, argv + 1 ) ) + error_exit( "%s", action ); - if( actions[i].action( argc, argv ) ) - error_exit( "%s", action ); - - handled = TRUE; - break; - } + handled = TRUE; + break; + } /* Could be a vips7 im_function. */ - if( !handled && (fn = im_find_function( action )) ) { + if( action && !handled && (fn = im_find_function( action )) ) { parse_options( context, &argc, argv ); - if( im_run_command( action, argc, argv ) ) { - if( argc == 0 ) + if( im_run_command( action, argc - 1, argv + 1 ) ) { + if( argc == 1 ) usage( fn ); else error_exit( NULL ); @@ -1070,20 +1077,17 @@ main( int argc, char **argv ) /* Could be a vips8 VipsOperation. */ - if( !handled && (operation = vips_operation_new( action )) ) { - GOptionGroup *group; - - if( !(group = vips_call_options( operation )) ) - error_exit( NULL ); - g_option_context_add_group( context, group ); + if( action && !handled && (operation = vips_operation_new( action )) ) { + main_group = add_main_group( context, operation ); + vips_call_options( main_group, operation ); parse_options( context, &argc, argv ); - - if( vips_call_argv( operation, argc, argv ) ) { - if( argc == 0 ) { + + if( vips_call_argv( operation, argc - 1, argv + 1 ) ) { + if( argc == 1 ) { char *help; help = g_option_context_get_help( context, - FALSE, group ); + FALSE, NULL ); printf( "%s", help ); vips_object_print( VIPS_OBJECT( operation ) ); error_exit( NULL ); @@ -1099,6 +1103,7 @@ main( int argc, char **argv ) im_error_clear(); if( !handled ) { + (void) add_main_group( context, NULL ); parse_options( context, &argc, argv ); if( argc > 1 )