},
CommandOptions[] =
{
+ /* WARNING: this must be sorted by name, then by switch character
+ So that it can be referanced using a binary search for speed.
+ See GetCommandOptionInfo() below for details.
+
+ Check on sort...
+ magick -list command > t1
+ sort -k 1.2 t1 | diff t1 -
+ Should not show any differences...
+ */
{ "(", 0L, SpecialOptionFlag, MagickTrue },
{ ")", 0L, SpecialOptionFlag, MagickTrue },
- { "+adjoin", 0L, ImageInfoOptionFlag, MagickFalse },
- { "-adjoin", 0L, ImageInfoOptionFlag, MagickFalse },
{ "+adaptive-blur", 1L, DeprecateOptionFlag, MagickTrue },
{ "-adaptive-blur", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+adaptive-resize", 1L, DeprecateOptionFlag, MagickTrue },
{ "-adaptive-resize", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+adaptive-sharpen", 1L, DeprecateOptionFlag, MagickTrue },
{ "-adaptive-sharpen", 1L, SimpleOperatorOptionFlag, MagickFalse },
+ { "+adjoin", 0L, ImageInfoOptionFlag, MagickFalse },
+ { "-adjoin", 0L, ImageInfoOptionFlag, MagickFalse },
{ "+affine", 0L, DrawInfoOptionFlag | DeprecateOptionFlag, MagickTrue },
{ "-affine", 1L, DrawInfoOptionFlag | DeprecateOptionFlag, MagickTrue },
{ "+affinity", 0L, DeprecateOptionFlag, MagickTrue },
{ "-clut", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse },
{ "+coalesce", 0L, FireOptionFlag | DeprecateOptionFlag, MagickTrue },
{ "-coalesce", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse },
+ { "+color-matrix", 1L, DeprecateOptionFlag, MagickTrue },
+ { "-color-matrix", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+colorize", 1L, DeprecateOptionFlag, MagickTrue },
{ "-colorize", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+colormap", 0L, NonConvertOptionFlag, MagickFalse },
{ "-colormap", 1L, NonConvertOptionFlag, MagickFalse },
- { "+color-matrix", 1L, DeprecateOptionFlag, MagickTrue },
- { "-color-matrix", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+colors", 1L, DeprecateOptionFlag, MagickTrue },
{ "-colors", 1L, ImageInfoOptionFlag, MagickFalse },
{ "+colorspace", 0L, ImageInfoOptionFlag | SimpleOperatorOptionFlag, MagickFalse },
{ "-flatten", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse },
{ "+flip", 0L, DeprecateOptionFlag, MagickTrue },
{ "-flip", 0L, SimpleOperatorOptionFlag, MagickFalse },
- { "+flop", 0L, DeprecateOptionFlag, MagickTrue },
- { "-flop", 0L, SimpleOperatorOptionFlag, MagickFalse },
{ "+floodfill", 2L, SimpleOperatorOptionFlag, MagickFalse },
{ "-floodfill", 2L, SimpleOperatorOptionFlag, MagickFalse },
+ { "+flop", 0L, DeprecateOptionFlag, MagickTrue },
+ { "-flop", 0L, SimpleOperatorOptionFlag, MagickFalse },
{ "+font", 0L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "-font", 1L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "+foreground", 0L, NonConvertOptionFlag, MagickFalse },
{ "-interline-spacing", 1L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "+interpolate", 0L, ImageInfoOptionFlag, MagickFalse },
{ "-interpolate", 1L, ImageInfoOptionFlag, MagickFalse },
- { "+interword-spacing", 0L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
- { "-interword-spacing", 1L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "+interpolative-resize", 1L, DeprecateOptionFlag, MagickTrue },
{ "-interpolative-resize", 1L, SimpleOperatorOptionFlag, MagickFalse },
+ { "+interword-spacing", 0L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
+ { "-interword-spacing", 1L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "+kerning", 0L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "-kerning", 1L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse },
{ "+label", 0L, ImageInfoOptionFlag, MagickFalse },
{ "-regard-warnings", 0L, GenesisOptionFlag, MagickFalse },
{ "+region", 0L, SpecialOptionFlag, MagickFalse },
{ "-region", 1L, SpecialOptionFlag, MagickFalse },
+ { "+remap", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse },
+ { "-remap", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+remote", 0L, NonConvertOptionFlag, MagickFalse },
{ "-remote", 1L, NonConvertOptionFlag, MagickFalse },
{ "+render", 0L, DrawInfoOptionFlag, MagickFalse },
{ "-render", 0L, DrawInfoOptionFlag, MagickFalse },
- { "+remap", 0L, ListOperatorOptionFlag | FireOptionFlag, MagickFalse },
- { "-remap", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+repage", 0L, SimpleOperatorOptionFlag, MagickFalse },
{ "-repage", 1L, SimpleOperatorOptionFlag, MagickFalse },
{ "+resample", 1L, DeprecateOptionFlag, MagickTrue },
{ (char *) NULL, UndefinedVirtualPixelMethod, UndefinedOptionFlag, MagickFalse }
};
\f
+static const OptionInfo *GetOptionInfo(const CommandOption option)
+{
+ switch (option)
+ {
+ case MagickAlignOptions: return(AlignOptions);
+ case MagickAlphaOptions: return(AlphaOptions);
+ case MagickBooleanOptions: return(BooleanOptions);
+ case MagickChannelOptions: return(ChannelOptions);
+ case MagickClassOptions: return(ClassOptions);
+ case MagickClipPathOptions: return(ClipPathOptions);
+ case MagickColorspaceOptions: return(ColorspaceOptions);
+ case MagickCommandOptions: return(CommandOptions);
+ case MagickComposeOptions: return(ComposeOptions);
+ case MagickCompressOptions: return(CompressOptions);
+ case MagickDataTypeOptions: return(DataTypeOptions);
+ case MagickDebugOptions: return(LogEventOptions);
+ case MagickDecorateOptions: return(DecorateOptions);
+ case MagickDirectionOptions: return(DirectionOptions);
+ case MagickDisposeOptions: return(DisposeOptions);
+ case MagickDistortOptions: return(DistortOptions);
+ case MagickDitherOptions: return(DitherOptions);
+ case MagickEndianOptions: return(EndianOptions);
+ case MagickEvaluateOptions: return(EvaluateOptions);
+ case MagickFillRuleOptions: return(FillRuleOptions);
+ case MagickFilterOptions: return(FilterOptions);
+ case MagickFunctionOptions: return(FunctionOptions);
+ case MagickGravityOptions: return(GravityOptions);
+/* case MagickImageListOptions: return(ImageListOptions); */
+ case MagickIntentOptions: return(IntentOptions);
+ case MagickInterlaceOptions: return(InterlaceOptions);
+ case MagickInterpolateOptions: return(InterpolateOptions);
+ case MagickKernelOptions: return(KernelOptions);
+ case MagickLayerOptions: return(LayerOptions);
+ case MagickLineCapOptions: return(LineCapOptions);
+ case MagickLineJoinOptions: return(LineJoinOptions);
+ case MagickListOptions: return(ListOptions);
+ case MagickLogEventOptions: return(LogEventOptions);
+ case MagickMetricOptions: return(MetricOptions);
+ case MagickMethodOptions: return(MethodOptions);
+ case MagickModeOptions: return(ModeOptions);
+ case MagickMorphologyOptions: return(MorphologyOptions);
+ case MagickNoiseOptions: return(NoiseOptions);
+ case MagickOrientationOptions: return(OrientationOptions);
+ case MagickPixelChannelOptions: return(PixelChannelOptions);
+ case MagickPixelTraitOptions: return(PixelTraitOptions);
+ case MagickPolicyDomainOptions: return(PolicyDomainOptions);
+ case MagickPolicyRightsOptions: return(PolicyRightsOptions);
+ case MagickPreviewOptions: return(PreviewOptions);
+ case MagickPrimitiveOptions: return(PrimitiveOptions);
+ case MagickQuantumFormatOptions: return(QuantumFormatOptions);
+ case MagickResolutionOptions: return(ResolutionOptions);
+ case MagickResourceOptions: return(ResourceOptions);
+ case MagickSparseColorOptions: return(SparseColorOptions);
+ case MagickStatisticOptions: return(StatisticOptions);
+ case MagickStorageOptions: return(StorageOptions);
+ case MagickStretchOptions: return(StretchOptions);
+ case MagickStyleOptions: return(StyleOptions);
+ case MagickTypeOptions: return(TypeOptions);
+ case MagickValidateOptions: return(ValidateOptions);
+ case MagickVirtualPixelOptions: return(VirtualPixelOptions);
+ default: break;
+ }
+ return((const OptionInfo *) NULL);
+}
+\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
%
*/
-static const OptionInfo *GetOptionInfo(const CommandOption option)
-{
- switch (option)
- {
- case MagickAlignOptions: return(AlignOptions);
- case MagickAlphaOptions: return(AlphaOptions);
- case MagickBooleanOptions: return(BooleanOptions);
- case MagickChannelOptions: return(ChannelOptions);
- case MagickClassOptions: return(ClassOptions);
- case MagickClipPathOptions: return(ClipPathOptions);
- case MagickColorspaceOptions: return(ColorspaceOptions);
- case MagickCommandOptions: return(CommandOptions);
- case MagickComposeOptions: return(ComposeOptions);
- case MagickCompressOptions: return(CompressOptions);
- case MagickDataTypeOptions: return(DataTypeOptions);
- case MagickDebugOptions: return(LogEventOptions);
- case MagickDecorateOptions: return(DecorateOptions);
- case MagickDirectionOptions: return(DirectionOptions);
- case MagickDisposeOptions: return(DisposeOptions);
- case MagickDistortOptions: return(DistortOptions);
- case MagickDitherOptions: return(DitherOptions);
- case MagickEndianOptions: return(EndianOptions);
- case MagickEvaluateOptions: return(EvaluateOptions);
- case MagickFillRuleOptions: return(FillRuleOptions);
- case MagickFilterOptions: return(FilterOptions);
- case MagickFunctionOptions: return(FunctionOptions);
- case MagickGravityOptions: return(GravityOptions);
-/* case MagickImageListOptions: return(ImageListOptions); */
- case MagickIntentOptions: return(IntentOptions);
- case MagickInterlaceOptions: return(InterlaceOptions);
- case MagickInterpolateOptions: return(InterpolateOptions);
- case MagickKernelOptions: return(KernelOptions);
- case MagickLayerOptions: return(LayerOptions);
- case MagickLineCapOptions: return(LineCapOptions);
- case MagickLineJoinOptions: return(LineJoinOptions);
- case MagickListOptions: return(ListOptions);
- case MagickLogEventOptions: return(LogEventOptions);
- case MagickMetricOptions: return(MetricOptions);
- case MagickMethodOptions: return(MethodOptions);
- case MagickModeOptions: return(ModeOptions);
- case MagickMorphologyOptions: return(MorphologyOptions);
- case MagickNoiseOptions: return(NoiseOptions);
- case MagickOrientationOptions: return(OrientationOptions);
- case MagickPixelChannelOptions: return(PixelChannelOptions);
- case MagickPixelTraitOptions: return(PixelTraitOptions);
- case MagickPolicyDomainOptions: return(PolicyDomainOptions);
- case MagickPolicyRightsOptions: return(PolicyRightsOptions);
- case MagickPreviewOptions: return(PreviewOptions);
- case MagickPrimitiveOptions: return(PrimitiveOptions);
- case MagickQuantumFormatOptions: return(QuantumFormatOptions);
- case MagickResolutionOptions: return(ResolutionOptions);
- case MagickResourceOptions: return(ResourceOptions);
- case MagickSparseColorOptions: return(SparseColorOptions);
- case MagickStatisticOptions: return(StatisticOptions);
- case MagickStorageOptions: return(StorageOptions);
- case MagickStretchOptions: return(StretchOptions);
- case MagickStyleOptions: return(StyleOptions);
- case MagickTypeOptions: return(TypeOptions);
- case MagickValidateOptions: return(ValidateOptions);
- case MagickVirtualPixelOptions: return(VirtualPixelOptions);
- default: break;
- }
- return((const OptionInfo *) NULL);
-}
-
MagickExport ssize_t GetCommandOptionFlags(const CommandOption option,
const MagickBooleanType list,const char *options)
{
% %
% %
% %
+% G e t C o m m a n d O p t i o n I n f o %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetCommandOptionInfo() returns pointer to the matching OptionInfo entry
+% for the "CommandOptions" table only. A specialised binary search is used,
+% to speed up the lookup for that very large table, and returns both the
+% type (arg count) and flags (arg type).
+%
+% This search reduces linear search of over 500 options (250 tests of
+% average) to about 10 lookups!
+%
+% The format of the GetCommandOptionInfo method is:
+%
+% const char **GetCommandOptions(const CommandOption value)
+%
+% A description of each parameter follows:
+%
+% o value: the value.
+%
+*/
+MagickExport const OptionInfo *GetCommandOptionInfo(const char *value)
+{
+ const OptionInfo
+ *option_info=CommandOptions;
+
+ static ssize_t
+ table_size = 0;
+
+ register ssize_t
+ i,l,h;
+
+ assert(value != (char *) NULL);
+ assert(*value != '\0');
+
+ /* count up table items - first time only */
+ if ( table_size == 0 )
+ {
+ l=-1;
+ for (i=0; option_info[i].mnemonic != (const char *) NULL; i++)
+ if ( LocaleCompare(value,option_info[i].mnemonic) == 0 )
+ l=i;
+ table_size = i;
+ return( &option_info[(l>=0?l:i)] );
+ }
+
+ /* faster binary search of command table, now that its length is known */
+ l=0;
+ h=table_size-1;
+ while ( l < h )
+ {
+ int cmp;
+ i = (l+h)/2; /* half the bounds */
+ /* compare string part, then switch character! */
+ cmp=LocaleCompare(value+1,option_info[i].mnemonic+1);
+ if ( cmp == 0 )
+ cmp = *value - *(option_info[i].mnemonic);
+
+fprintf(stderr, "%d --- %u < %u < %u --- \"%s\" < \"%s\" < \"%s\"\n",
+ cmp, l,i,h,
+ option_info[l].mnemonic, option_info[i].mnemonic, option_info[h].mnemonic);
+
+ if (cmp == 0)
+ return(&option_info[i]);
+ if (cmp > 0) l=i+1; else h=i; /* reassign search bounds */
+ }
+ /* option was not found in table - return last 'null' entry. */
+ return(&option_info[table_size]);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% G e t C o m m a n d O p t i o n s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% MagickCommandsProcessOptions() reads and processes arguments in the given
+% MagickCommandProcessOptions() reads and processes arguments in the given
% command line argument array.
%
% The format of the MagickImageCommand method is:
%
-% void MagickCommandArgs(MagickWand *wand,int argc,char **argv)
+% void MagickCommandArgs(MagickWand *wand,int argc,char **argv,
+% int *index, )
%
% A description of each parameter follows:
%
%
% o argv: A text array containing the command line arguments.
%
+% o index: where we are upto in processing given arguments
+%
+% o flags: Allow or disallow specific options
*/
#define MagickExceptionContinue(severity,tag,option,arg) \
(void) ThrowMagickException(wand->exception,GetMagickModule(),severity,tag, \
}
WandExport void MagickCommandProcessOptions(MagickWand *wand,int argc,
- char **argv)
+ char **argv, int *index, OptionProcessFlags process_flags )
{
const char
*option,
count;
CommandOptionFlags
- flags;
+ option_type;
assert(wand != (MagickWand *) NULL);
assert(wand->signature == WandSignature);
Parse command-line options.
*/
count=0;
- for (i=1; i < (ssize_t) (argc-1); i+=count+1)
+ for (i=*index; i < (ssize_t) (argc-1); i+=count+1)
{
+ *index=i;
option=argv[i];
plus_alt_op = MagickFalse;
arg1=(char *)NULL;
arg2=(char *)NULL;
- /* FUTURE: merge these into one call */
+#define MagickCommandDebug 1
+#if 1
+ { const OptionInfo *option_info =
+ GetCommandOptionInfo(argv[i]);
+ count=option_info->type;
+ option_type=option_info->flags;
+#if MagickCommandDebug
+ (void) FormatLocaleFile(stderr, "Option: \"%s\"\n", option_info->mnemonic);
+#endif
+ }
+#else
count=ParseCommandOption(MagickCommandOptions,MagickFalse,argv[i]);
- flags=(CommandOptionFlags) GetCommandOptionFlags(
+ option_type=(CommandOptionFlags) GetCommandOptionFlags(
MagickCommandOptions,MagickFalse,argv[i]);
+#endif
-#define MagickCommandDebug 1
- if ( count == -1 || flags == UndefinedOptionFlag ||
- (flags & NonConvertOptionFlag) != 0 )
+ if ( count == -1 || option_type == UndefinedOptionFlag ||
+ (option_type & NonConvertOptionFlag) != 0 )
{
#if MagickCommandDebug
(void) FormatLocaleFile(stderr, "CLI Non-Option: \"%s\"\n", option);
#endif
+
if (IsCommandOption(option) == MagickFalse)
{
/* non-option -- treat as a image read */
MagickExceptionReturn(OptionError,"UnrecognizedOption",option,i);
}
- if ( (flags & DeprecateOptionFlag) != 0 )
+#if MagickCommandDebug
+ (void) FormatLocaleFile(stderr,
+ "CLI Option: \"%s\" \tCount: %d Flags: %04x Args: \"%s\" \"%s\"\n",
+ option,(int) count,option_type,arg1,arg2);
+#endif
+
+ if ( (option_type & DeprecateOptionFlag) != 0 )
MagickExceptionContinue(OptionWarning,"DeprecatedOption",option,i);
/* continue processing option anyway */
if ( count >= 1 ) arg1 = argv[i+1];
if ( count >= 2 ) arg2 = argv[i+2];
-#if MagickCommandDebug
- (void) FormatLocaleFile(stderr,
- "CLI Option: \"%s\" \tCount: %d Flags: %04x Args: \"%s\" \"%s\"\n",
- option,(int) count,flags,arg1,arg2);
-#endif
-
- if ( (flags & SpecialOptionFlag) != 0 )
+ if ( (option_type & SpecialOptionFlag) != 0 )
{
if (LocaleCompare(option,"-exit") == 0)
return;
MagickSpecialOption(wand,option,arg1);
}
- if ( (flags & SettingOptionFlags) != 0 )
+ if ( (option_type & SettingOptionFlags) != 0 )
{
WandSettingOptionInfo(wand, option+1, arg1);
// FUTURE: Sync Specific Settings into Images
}
- if ( (flags & SimpleOperatorOptionFlag) != 0)
+ if ( (option_type & SimpleOperatorOptionFlag) != 0)
{
WandSimpleOperatorImages(wand, plus_alt_op, option+1, arg1, arg2);
}
- if ( (flags & ListOperatorOptionFlag) != 0 )
+ if ( (option_type & ListOperatorOptionFlag) != 0 )
{
WandListOperatorImages(wand, plus_alt_op, option+1, arg1, arg2);
}
assert(i==(ssize_t)(argc-1));
option=argv[i]; /* the last argument - output filename! */
+
#if MagickCommandDebug
(void) FormatLocaleFile(stderr, "CLI Output: \"%s\"\n", option );
#endif
ThrowConvertException(ResourceLimitError,"MemoryAllocationFailed",
GetExceptionMessage(errno));
#endif
+
+ /* Special hidden option for 'delegates' */
if (LocaleCompare("-concatenate",argv[1]) == 0)
return(ConcatenateImages(argc,argv,exception));
- /* create a special CLI Wand to hold all working settings */
+ /* Create a special "CLI Wand" to hold images and settings */
/* FUTURE: add this to 'operations.c' */
wand=NewMagickWand();
wand->image_info=DestroyImageInfo(wand->image_info);
if (LocaleCompare("-list",argv[1]) == 0)
WandSettingOptionInfo(wand, argv[1]+1, argv[2]);
+#if 0
+ else if (LocaleCompare("-script",argv[1]) == 0)
+ {
+ /* Start processing from script, no pre-script options */
+ int
+ index;
+
+ index=2;
+ GetPathComponent(argv[2],TailPath,wand->name);
+ MagickScriptProcessOptions(wand,argc,argv,&index);
+ }
+#endif
else
- MagickCommandProcessOptions(wand,argc,argv);
+ {
+ /* Processing Command line, assuming output file as last option */
+ int
+ index;
+
+ index=1;
+ GetPathComponent(argv[0],TailPath,wand->name);
+ MagickCommandProcessOptions(wand,argc,argv, &index,
+ ProcessCommandOptions|ProcessOutputFile);
+ }
assert(wand->exception == exception);
assert(wand->image_info == image_info);