Пример #1
0
static void MagickUsage(MagickBooleanType verbose)
{
  const char
    *name;

  size_t
    len;

  name=GetClientName();
  len=strlen(name);

  if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
    /* convert usage */
    (void) FormatLocaleFile(stdout,
       "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
    (void) FormatLocaleFile(stdout,
       "       %s -help | -version | -usage | -list {option}\n\n",name);
    return;
  }
  else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
    /* magick-script usage */
    (void) FormatLocaleFile(stdout,
      "Usage: %s {filename} [ {script_args} ... ]\n",name);
  }
  else {
    /* magick usage */
    (void) FormatLocaleFile(stdout,
       "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
    (void) FormatLocaleFile(stdout,
       "       %s [ {option} | {image} ... ] -script {filename} [ {script_args} ...]\n",
       name);
  }
  (void) FormatLocaleFile(stdout,
    "       %s -help | -version | -usage | -list {option}\n\n",name);

  if (IfMagickFalse(verbose))
    return;

  (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
    "All options are performed in a strict 'as you see them' order\n",
    "You must read-in images before you can operate on them.\n",
    "\n",
    "Magick Script files can use any of the following forms...\n",
    "     #!/path/to/magick -script\n",
    "or\n",
    "     #!/bin/sh\n",
    "     :; exec magick -script \"$0\" \"$@\"; exit 10\n",
    "     # Magick script from here...\n",
    "or\n",
    "     #!/usr/bin/env  magick-script\n",
    "The latter two forms do not require the path to the command hard coded.\n",
    "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
    "\n",
    "For more information on usage, options, examples, and techniques\n",
    "see the ImageMagick website at    ", MagickAuthoritativeURL);

  return;
}
Пример #2
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   C L I C a t c h E x c e p t i o n                                         %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  CLICatchException() will report exceptions, either just non-fatal warnings
%  only, or all errors, according to 'all_execeptions' boolean argument.
%
%  The function returns true if errors are fatal, in which case the caller
%  should abort and re-call with an 'all_exceptions' argument of true before
%  quitting.
%
%  The cut-off level between fatal and non-fatal may be controlled by options
%  (FUTURE), but defaults to 'Error' exceptions.
%
%  The format of the CLICatchException method is:
%
%    MagickBooleanType CLICatchException(MagickCLI *cli_wand,
%              const MagickBooleanType all_exceptions );
%
%  Arguments are
%
%    o cli_wand:   The Wand CLI that holds the exception Information
%
%    o all_exceptions:   Report all exceptions, including the fatal one
%
*/
WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
     const MagickBooleanType all_exceptions )
{
  MagickBooleanType
    status;
  assert(cli_wand != (MagickCLI *) NULL);
  assert(cli_wand->signature == WandSignature);
  assert(cli_wand->wand.signature == WandSignature);
  if (IfMagickTrue(cli_wand->wand.debug))
    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);

  // FUTURE: '-regard_warning' should make this more sensitive.
  // Note pipelined options may like more control over this level

  status = IsMagickTrue(cli_wand->wand.exception->severity > ErrorException);

  if ( IfMagickFalse(status) || IfMagickTrue(all_exceptions) )
    CatchException(cli_wand->wand.exception); /* output and clear exceptions */

  return(status);
}
Пример #3
0
/*
   Concatanate given file arguments to the given output argument.
   Used for a special -concatenate option used for specific 'delegates'.
   The option is not formally documented.

      magick -concatenate files... output

   This is much like the UNIX "cat" command, but for both UNIX and Windows,
   however the last argument provides the output filename.
*/
static MagickBooleanType ConcatenateImages(int argc,char **argv,
     ExceptionInfo *exception )
{
  FILE
    *input,
    *output;

  int
    c;

  register ssize_t
    i;

  if (IfMagickFalse(  ExpandFilenames(&argc,&argv)  ))
    ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
         GetExceptionMessage(errno));

  output=fopen_utf8(argv[argc-1],"wb");
  if (output == (FILE *) NULL) {
    ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
    return(MagickFalse);
  }
  for (i=2; i < (ssize_t) (argc-1); i++) {
#if 0
    fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
#endif
    input=fopen_utf8(argv[i],"rb");
    if (input == (FILE *) NULL) {
        ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
        continue;
      }
    for (c=fgetc(input); c != EOF; c=fgetc(input))
      (void) fputc((char) c,output);
    (void) fclose(input);
    (void) remove_utf8(argv[i]);
  }
  (void) fclose(output);
  return(MagickTrue);
}
Пример #4
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e I m a g e                                                       %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WriteImage() writes an image or an image sequence to a file or file handle.
%  If writing to a file is on disk, the name is defined by the filename member
%  of the image structure.  WriteImage() returns MagickFalse is there is a
%  memory shortage or if the image cannot be written.  Check the exception
%  member of image to determine the cause for any failure.
%
%  The format of the WriteImage method is:
%
%      MagickBooleanType WriteImage(const ImageInfo *image_info,Image *image,
%        ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o image_info: the image info.
%
%    o image: the image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType WriteImage(const ImageInfo *image_info,
  Image *image,ExceptionInfo *exception)
{
  char
    filename[MaxTextExtent];

  const char
    *option;

  const DelegateInfo
    *delegate_info;

  const MagickInfo
    *magick_info;

  ExceptionInfo
    *sans_exception;

  ImageInfo
    *write_info;

  MagickBooleanType
    status,
    temporary;

  MagickStatusType
    thread_support;

  PolicyDomain
    domain;

  PolicyRights
    rights;

  /*
    Determine image type from filename prefix or suffix (e.g. image.jpg).
  */
  assert(image_info != (ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  assert(exception != (ExceptionInfo *) NULL);
  sans_exception=AcquireExceptionInfo();
  write_info=CloneImageInfo(image_info);
  (void) CopyMagickString(write_info->filename,image->filename,MaxTextExtent);
  if (*write_info->magick == '\0')
    (void) CopyMagickString(write_info->magick,image->magick,MaxTextExtent);
  (void) SetImageInfo(write_info,1,sans_exception);
  (void) CopyMagickString(filename,image->filename,MaxTextExtent);
  (void) CopyMagickString(image->filename,write_info->filename,MaxTextExtent);
  domain=CoderPolicyDomain;
  rights=WritePolicyRights;
  if (IsRightsAuthorized(domain,rights,write_info->magick) == MagickFalse)
    {
      sans_exception=DestroyExceptionInfo(sans_exception);
      write_info=DestroyImageInfo(write_info);
      errno=EPERM;
      ThrowBinaryException(PolicyError,"NotAuthorized",filename);
    }
  /*
    Call appropriate image reader based on image type.
  */
  magick_info=GetMagickInfo(write_info->magick,sans_exception);
  sans_exception=DestroyExceptionInfo(sans_exception);
  if (magick_info != (const MagickInfo *) NULL)
    {
      if (GetMagickEndianSupport(magick_info) == MagickFalse)
        image->endian=UndefinedEndian;
      else
        if ((image_info->endian == UndefinedEndian) &&
            (GetMagickRawSupport(magick_info) != MagickFalse))
          {
            size_t
              lsb_first;

            lsb_first=1;
            image->endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
         }
    }
  (void) SyncImageProfiles(image);
  DisassociateImageStream(image);
  option=GetImageOption(image_info,"delegate:bimodal");
  if ((IfMagickTrue(IsStringTrue(option))) &&
      (write_info->page == (char *) NULL) &&
      (GetPreviousImageInList(image) == (Image *) NULL) &&
      (GetNextImageInList(image) == (Image *) NULL) &&
      (IfMagickFalse(IsTaintImage(image))) )
    {
      delegate_info=GetDelegateInfo(image->magick,write_info->magick,exception);
      if ((delegate_info != (const DelegateInfo *) NULL) &&
          (GetDelegateMode(delegate_info) == 0) &&
          (IsPathAccessible(image->magick_filename) != MagickFalse))
        {
          /*
            Process image with bi-modal delegate.
          */
          (void) CopyMagickString(image->filename,image->magick_filename,
            MaxTextExtent);
          status=InvokeDelegate(write_info,image,image->magick,
            write_info->magick,exception);
          write_info=DestroyImageInfo(write_info);
          (void) CopyMagickString(image->filename,filename,MaxTextExtent);
          return(status);
        }
    }
  status=MagickFalse;
  temporary=MagickFalse;
  if ((magick_info != (const MagickInfo *) NULL) &&
      (GetMagickSeekableStream(magick_info) != MagickFalse))
    {
      char
        filename[MaxTextExtent];

      (void) CopyMagickString(filename,image->filename,MaxTextExtent);
      status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
      (void) CopyMagickString(image->filename,filename,MaxTextExtent);
      if (status != MagickFalse)
        {
          if (IsBlobSeekable(image) == MagickFalse)
            {
              /*
                A seekable stream is required by the encoder.
              */
              write_info->adjoin=MagickTrue;
              (void) CopyMagickString(write_info->filename,image->filename,
                MaxTextExtent);
              (void) AcquireUniqueFilename(image->filename);
              temporary=MagickTrue;
            }
          (void) CloseBlob(image);
        }
    }
  if ((magick_info != (const MagickInfo *) NULL) &&
      (GetImageEncoder(magick_info) != (EncodeImageHandler *) NULL))
    {
      /*
        Call appropriate image writer based on image type.
      */
      thread_support=GetMagickThreadSupport(magick_info);
      if ((thread_support & EncoderThreadSupport) == 0)
        LockSemaphoreInfo(magick_info->semaphore);
      status=GetImageEncoder(magick_info)(write_info,image,exception);
      if ((thread_support & EncoderThreadSupport) == 0)
        UnlockSemaphoreInfo(magick_info->semaphore);
    }
  else
    {
      delegate_info=GetDelegateInfo((char *) NULL,write_info->magick,exception);
      if (delegate_info != (DelegateInfo *) NULL)
        {
          /*
            Process the image with delegate.
          */
          *write_info->filename='\0';
          if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
            LockSemaphoreInfo(delegate_info->semaphore);
          status=InvokeDelegate(write_info,image,(char *) NULL,
            write_info->magick,exception);
          if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
            UnlockSemaphoreInfo(delegate_info->semaphore);
          (void) CopyMagickString(image->filename,filename,MaxTextExtent);
        }
      else
        {
          sans_exception=AcquireExceptionInfo();
          magick_info=GetMagickInfo(write_info->magick,sans_exception);
          sans_exception=DestroyExceptionInfo(sans_exception);
          if ((write_info->affirm == MagickFalse) &&
              (magick_info == (const MagickInfo *) NULL))
            {
              (void) CopyMagickString(write_info->magick,image->magick,
                MaxTextExtent);
              magick_info=GetMagickInfo(write_info->magick,exception);
            }
          if ((magick_info == (const MagickInfo *) NULL) ||
              (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL))
            {
              char
                extension[MaxTextExtent];

              GetPathComponent(image->filename,ExtensionPath,extension);
              if (*extension != '\0')
                magick_info=GetMagickInfo(extension,exception);
              else
                magick_info=GetMagickInfo(image->magick,exception);
              (void) CopyMagickString(image->filename,filename,MaxTextExtent);
            }
          if ((magick_info == (const MagickInfo *) NULL) ||
              (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL))
            {
              magick_info=GetMagickInfo(image->magick,exception);
              if ((magick_info == (const MagickInfo *) NULL) ||
                  (GetImageEncoder(magick_info) == (EncodeImageHandler *) NULL))
                (void) ThrowMagickException(exception,GetMagickModule(),
                  MissingDelegateError,"NoEncodeDelegateForThisImageFormat",
                  "`%s'",write_info->magick);
              else
                (void) ThrowMagickException(exception,GetMagickModule(),
                  MissingDelegateWarning,"NoEncodeDelegateForThisImageFormat",
                  "`%s'",write_info->magick);
            }
          if ((magick_info != (const MagickInfo *) NULL) &&
              (GetImageEncoder(magick_info) != (EncodeImageHandler *) NULL))
            {
              /*
                Call appropriate image writer based on image type.
              */
              thread_support=GetMagickThreadSupport(magick_info);
              if ((thread_support & EncoderThreadSupport) == 0)
                LockSemaphoreInfo(magick_info->semaphore);
              status=GetImageEncoder(magick_info)(write_info,image,exception);
              if ((thread_support & EncoderThreadSupport) == 0)
                UnlockSemaphoreInfo(magick_info->semaphore);
            }
        }
    }
  if (GetBlobError(image) != MagickFalse)
    ThrowFileException(exception,FileOpenError,
      "AnErrorHasOccurredWritingToFile",image->filename);
  if (temporary != MagickFalse)
    {
      /*
        Copy temporary image file to permanent.
      */
      status=OpenBlob(write_info,image,ReadBinaryBlobMode,exception);
      if (status != MagickFalse)
        {
          (void) RelinquishUniqueFileResource(write_info->filename);
          status=ImageToFile(image,write_info->filename,exception);
        }
      (void) CloseBlob(image);
      (void) RelinquishUniqueFileResource(image->filename);
      (void) CopyMagickString(image->filename,write_info->filename,
        MaxTextExtent);
    }
  if ((LocaleCompare(write_info->magick,"info") != 0) &&
      (write_info->verbose != MagickFalse))
    (void) IdentifyImage(image,stdout,MagickFalse,exception);
  write_info=DestroyImageInfo(write_info);
  return(status);
}
Пример #5
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+  P r o c e s s C o m m a n d O p t i o n s                                  %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ProcessCommandOptions() reads and processes arguments in the given
%  command line argument array. The 'index' defines where in the array we
%  should begin processing
%
%  The 'process_flags' can be used to control and limit option processing.
%  For example, to only process one option, or how unknown and special options
%  are to be handled, and if the last argument in array is to be regarded as a
%  final image write argument (filename or special coder).
%
%  The format of the ProcessCommandOptions method is:
%
%    int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
%      int index)
%
%  A description of each parameter follows:
%
%    o cli_wand: the main CLI Wand to use.
%
%    o argc: the number of elements in the argument vector.
%
%    o argv: A text array containing the command line arguments.
%
%    o process_flags: What type of arguments will be processed, ignored
%                     or return errors.
%
%    o index: index in the argv array to start processing from
%
% The function returns the index ot the next option to be processed. This
% is really only releven if process_flags contains a ProcessOneOptionOnly
% flag.
%
*/
WandExport int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
  int index)
{
  const char
    *option,
    *arg1,
    *arg2;

  int
    i,
    end,
    count;

  CommandOptionFlags
    option_type;

  assert(argc>=index); /* you may have no arguments left! */
  assert(argv != (char **) NULL);
  assert(argv[index] != (char *) NULL);
  assert(argv[argc-1] != (char *) NULL);
  assert(cli_wand != (MagickCLI *) NULL);
  assert(cli_wand->signature == WandSignature);

  /* define the error location string for use in exceptions
     order of localtion format escapes: filename, line, column */
  cli_wand->location="at %s arg %u";
  cli_wand->filename="CLI";
  cli_wand->line=index;  /* note first argument we will process */

  if (IfMagickTrue(cli_wand->wand.debug))
    (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
         "- Starting (\"%s\")", argv[index]);

  end = argc;
  if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
    end--; /* the last arument is an implied write, do not process directly */

  for (i=index; i < end; i += count +1) {
    /* Finished processing one option? */
    if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
      return(i);

    do { /* use break to loop to exception handler and loop */

      option=argv[i];
      cli_wand->line=i;  /* note the argument for this option */

      /* get option, its argument count, and option type */
      cli_wand->command = GetCommandOptionInfo(argv[i]);
      count=cli_wand->command->type;
      option_type=(CommandOptionFlags) cli_wand->command->flags;
#if 0
      (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
            i, argv[i], cli_wand->command->mnemonic );
#endif

      if ( option_type == UndefinedOptionFlag ||
           (option_type & NonMagickOptionFlag) != 0 ) {
#if MagickCommandDebug >= 3
        (void) FormatLocaleFile(stderr, "CLI arg %d Non-Option: \"%s\"\n",
             i, option);
#endif
        if ( IfMagickFalse(IsCommandOption(option)) ) {
          if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
            /* non-option -- treat as a image read */
            cli_wand->command=(const OptionInfo *) NULL;
            CLIOption(cli_wand,"-read",option);
            break; /* next option */
          }
        }
        CLIWandException(OptionFatalError,"UnrecognizedOption",option);
        break; /* next option */
      }

      if ( ((option_type & SpecialOptionFlag) != 0 ) &&
           ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
           (LocaleCompare(option,"-script") == 0) ) {
        /* Call Script from CLI, with a filename as a zeroth argument.
           NOTE: -script may need to use the 'implict write filename' argument
           so it must be handled specially to prevent a 'missing argument' error.
        */
        if ( (i+count) >= argc )
          CLIWandException(OptionFatalError,"MissingArgument",option);
        ProcessScriptOptions(cli_wand,argv[i+1],argc,argv,i+count);
        return(argc);  /* Script does not return to CLI -- Yet */
                       /* FUTURE: when it does, their may be no write arg! */
      }

      if ((i+count) >= end ) {
        CLIWandException(OptionFatalError,"MissingArgument",option);
        if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
          return(end);
        break; /* next option - not that their is any! */
      }

      arg1 = ( count >= 1 ) ? argv[i+1] : (char *) NULL;
      arg2 = ( count >= 2 ) ? argv[i+2] : (char *) NULL;

      /*
        Process Known Options
      */
#if MagickCommandDebug >= 3
      (void) FormatLocaleFile(stderr,
        "CLI arg %u Option: \"%s\"  Count: %d  Flags: %04x  Args: \"%s\" \"%s\"\n",
            i,option,count,option_type,arg1,arg2);
#endif
      /* ignore 'genesis options' in command line args */
      if ( (option_type & GenesisOptionFlag) != 0 )
        break; /* next option */

      /* Handle any special options for CLI (-script handled above) */
      if ( (option_type & SpecialOptionFlag) != 0 ) {
        if ( (cli_wand->process_flags & ProcessExitOption) != 0
             && LocaleCompare(option,"-exit") == 0 )
          return(i+count);
        break; /* next option */
      }

      /* Process standard image option */
      CLIOption(cli_wand, option, arg1, arg2);

DisableMSCWarning(4127)
    } while (0); /* break block to next option */
RestoreMSCWarning

#if MagickCommandDebug >= 5
    (void) FormatLocaleFile(stderr, "CLI-post Image Count = %ld\n",
         (long) GetImageListLength(cli_wand->wand.images) );
#endif
    if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
      return(i+count);
  }
  assert(i==end);

  if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
    return(end); /* no implied write -- just return to caller */

  assert(end==argc-1); /* end should not include last argument */

  /*
     Implicit Write of images to final CLI argument
  */
  option=argv[i];
  cli_wand->line=i;

  /* check that stacks are empty - or cause exception */
  if (cli_wand->image_list_stack != (Stack *) NULL)
    CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
  else if (cli_wand->image_info_stack != (Stack *) NULL)
    CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
  if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
    return(argc);

#if MagickCommandDebug >= 3
  (void) FormatLocaleFile(stderr,"CLI arg %d Write File: \"%s\"\n",i,option);
#endif

  /* Valid 'do no write' replacement option (instead of "null:") */
  if (LocaleCompare(option,"-exit") == 0 )
    return(argc);  /* just exit, no image write */

  /* If filename looks like an option,
     Or the common 'end of line' error of a single space.
     -- produce an error */
  if (IfMagickTrue(IsCommandOption(option)) ||
      (option[0] == ' ' && option[1] == '\0') ) {
    CLIWandException(OptionError,"MissingOutputFilename",option);
    return(argc);
  }

  cli_wand->command=(const OptionInfo *) NULL;
  CLIOption(cli_wand,"-write",option);
  return(argc);
}
Пример #6
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   P r o c e s s S c r i p t O p t i o n s                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ProcessScriptOptions() reads options and processes options as they are
%  found in the given file, or pipeline.  The filename to open and read
%  options is given as the 'index' argument of the argument array given.
%
%  Other arguments following index may be read by special script options
%  as settings (strings), images, or as operations to be processed in various
%  ways.   How they are treated is up to the script being processed.
%
%  Note that a script not 'return' to the command line processing, nor can
%  they call (and return from) other scripts. At least not at this time.
%
%  There are no 'ProcessOptionFlags' control flags at this time.
%
%  The format of the ProcessScriptOptions method is:
%
%    void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
%       int argc,char **argv,int index)
%
%  A description of each parameter follows:
%
%    o cli_wand: the main CLI Wand to use.
%
%    o filename: the filename of script to process
%
%    o argc: the number of elements in the argument vector. (optional)
%
%    o argv: A text array containing the command line arguments. (optional)
%
%    o index: offset of next argment in argv (script arguments) (optional)
%
*/
WandExport void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
  int argc,char **argv,int index)
{
  ScriptTokenInfo
    *token_info;

  CommandOptionFlags
    option_type;

  int
    count;

  char
    *option,
    *arg1,
    *arg2;

  assert(filename != (char *) NULL ); /* at least one argument - script name */
  assert(cli_wand != (MagickCLI *) NULL);
  assert(cli_wand->signature == WandSignature);
  if (IfMagickTrue(cli_wand->wand.debug))
    (void) LogMagickEvent(CommandEvent,GetMagickModule(),
         "Processing script \"%s\"", filename);

  /* open file script or stream, and set up tokenizer */
  token_info = AcquireScriptTokenInfo(filename);
  if (token_info == (ScriptTokenInfo *) NULL) {
    CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",filename);
    return;
  }

  /* define the error location string for use in exceptions
     order of localtion format escapes: filename, line, column */
  cli_wand->location="in \"%s\" at line %u,column %u";
  if ( LocaleCompare("-", filename) == 0 )
    cli_wand->filename="stdin";
  else
    cli_wand->filename=filename;

  /* Process Options from Script */
  option = arg1 = arg2 = (char*) NULL;
DisableMSCWarning(4127)
  while (1) {
RestoreMSCWarning

    { MagickBooleanType status = GetScriptToken(token_info);
      cli_wand->line=token_info->token_line;
      cli_wand->column=token_info->token_column;
      if (status == MagickFalse)
        break; /* error or end of options */
    }

    do { /* use break to loop to exception handler and loop */

      /* save option details */
      CloneString(&option,token_info->token);

      /* get option, its argument count, and option type */
      cli_wand->command = GetCommandOptionInfo(option);
      count=cli_wand->command->type;
      option_type=(CommandOptionFlags) cli_wand->command->flags;
#if 0
      (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n",
          cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic );
#endif

      /* handle a undefined option - image read - always for "magick-script" */
      if ( option_type == UndefinedOptionFlag ||
           (option_type & NonMagickOptionFlag) != 0 ) {
#if MagickCommandDebug >= 3
        (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
                    cli_wand->line, cli_wand->line, option);
#endif
        if ( IfMagickFalse(IsCommandOption(option))) {
          /* non-option -- treat as a image read */
          cli_wand->command=(const OptionInfo *) NULL;
          CLIOption(cli_wand,"-read",option);
          break; /* next option */
        }
        CLIWandException(OptionFatalError,"UnrecognizedOption",option);
        break; /* next option */
      }

      if ( count >= 1 ) {
        if( IfMagickFalse(GetScriptToken(token_info)) )
          CLIWandException(OptionFatalError,"MissingArgument",option);
        CloneString(&arg1,token_info->token);
      }
      else
        CloneString(&arg1,(char *) NULL);

      if ( count >= 2 ) {
        if( IfMagickFalse(GetScriptToken(token_info)) )
          CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option);
        CloneString(&arg2,token_info->token);
      }
      else
        CloneString(&arg2,(char *) NULL);

      /*
        Process Options
      */
#if MagickCommandDebug >= 3
      (void) FormatLocaleFile(stderr,
        "Script %u,%u Option: \"%s\"  Count: %d  Flags: %04x  Args: \"%s\" \"%s\"\n",
            cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2);
#endif
      /* Hard Deprecated Options, no code to execute - error */
      if ( (option_type & DeprecateOptionFlag) != 0 ) {
        CLIWandException(OptionError,"DeprecatedOptionNoCode",option);
        break; /* next option */
      }

      /* MagickCommandGenesis() options have no place in a magick script */
      if ( (option_type & GenesisOptionFlag) != 0 ) {
        CLIWandException(OptionError,"InvalidUseOfOption",option);
        break; /* next option */
      }

      /* handle any special 'script' options */
      if ( (option_type & SpecialOptionFlag) != 0 ) {
        if ( LocaleCompare(option,"-exit") == 0 ) {
          goto loop_exit; /* break out of loop - return from script */
        }
        if ( LocaleCompare(option,"-script") == 0 ) {
          /* FUTURE: call new script from this script - error for now */
          CLIWandException(OptionError,"InvalidUseOfOption",option);
          break; /* next option */
        }
        /* FUTURE: handle special script-argument options here */
        /* handle any other special operators now */
        CLIWandException(OptionError,"InvalidUseOfOption",option);
        break; /* next option */
      }

      /* Process non-specific Option */
      CLIOption(cli_wand, option, arg1, arg2);
      (void) fflush(stdout);
      (void) fflush(stderr);

DisableMSCWarning(4127)
    } while (0); /* break block to next option */
RestoreMSCWarning

#if MagickCommandDebug >= 5
    fprintf(stderr, "Script Image Count = %ld\n",
         GetImageListLength(cli_wand->wand.images) );
#endif
    if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
      break;  /* exit loop */
  }

  /*
     Loop exit - check for some tokenization error
  */
loop_exit:
#if MagickCommandDebug >= 3
  (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
#endif
  switch( token_info->status ) {
    case TokenStatusOK:
    case TokenStatusEOF:
      if (cli_wand->image_list_stack != (Stack *) NULL)
        CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
      else if (cli_wand->image_info_stack != (Stack *) NULL)
        CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
      break;
    case TokenStatusBadQuotes:
      /* Ensure last token has a sane length for error report */
      if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
        token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
        token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
        token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
        token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
      }
      CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
           token_info->token);
      break;
    case TokenStatusMemoryFailed:
      CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
      break;
    case TokenStatusBinary:
      CLIWandException(OptionFatalError,"ScriptIsBinary","");
      break;
  }
  (void) fflush(stdout);
  (void) fflush(stderr);
  if (IfMagickTrue(cli_wand->wand.debug))
    (void) LogMagickEvent(CommandEvent,GetMagickModule(),
         "Script End \"%s\"", filename);

  /* Clean up */
  token_info = DestroyScriptTokenInfo(token_info);

  CloneString(&option,(char *) NULL);
  CloneString(&arg1,(char *) NULL);
  CloneString(&arg2,(char *) NULL);

  return;
}
Пример #7
0
WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,
  int argc,char **argv,char **metadata,ExceptionInfo *exception)
{
  MagickCLI
    *cli_wand;

  size_t
    len;

  /* For specific OS command line requirements */
  ReadCommandlLine(argc,&argv);

#if 0
  status=ExpandFilenames(&argc,&argv);
  if ( IfMagickFalse(status) )
    ThrowConvertException(ResourceLimitError,"MemoryAllocationFailed",
      GetExceptionMessage(errno));
#endif

  /* Initialize special "CLI Wand" to hold images and settings (empty) */
  cli_wand=AcquireMagickCLI(image_info,exception);
  cli_wand->line=1;

  GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
  SetClientName(cli_wand->wand.name);
  ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent);

  len=strlen(argv[0]);  /* precaution */

  /* "convert" command - give a "depreciation" warning" */
  if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
    cli_wand->process_flags = ConvertCommandOptionFlags;
    /*(void) FormatLocaleFile(stderr,"WARNING: %s\n",
             "The convert is depreciated in IMv7, use \"magick\"\n");*/
  }

  /* Special Case:  If command name ends with "script" implied "-script" */
  if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
    if (argc >= 2 && (  (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
      GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
      ProcessScriptOptions(cli_wand,argc,argv,1);
      goto Magick_Command_Cleanup;
    }
  }

  /* Special Case: Version Information and Abort */
  if (argc == 2) {
    if (LocaleCompare("-version",argv[1]) == 0) {
      CLISpecialOperator(cli_wand, "-version", (char *)NULL);
      goto Magick_Command_Exit;
    }
    if ((LocaleCompare("-help",argv[1]) == 0)   || /* GNU standard option */
        (LocaleCompare("--help",argv[1]) == 0) ) {
      MagickUsage(MagickFalse);
      goto Magick_Command_Exit;
    }
    if (LocaleCompare("-usage",argv[1]) == 0) {
      CLISpecialOperator(cli_wand, "-version", (char *)NULL);
      MagickUsage(MagickTrue);
      goto Magick_Command_Exit;
    }
  }

  /* not enough arguments -- including -help */
  if (argc < 3) {
    (void) FormatLocaleFile(stderr,
       "Error: Invalid argument or not enough arguments\n\n");
    MagickUsage(MagickFalse);
    goto Magick_Command_Exit;
  }

  /* List Information and Abort */
  if (LocaleCompare("-list",argv[1]) == 0) {
    CLISpecialOperator(cli_wand, argv[1], argv[2]);
    goto Magick_Command_Exit;
  }

  /* Special "concatenate option (hidden) for delegate usage */
  if (LocaleCompare("-concatenate",argv[1]) == 0) {
    ConcatenateImages(argc,argv,exception);
    goto Magick_Command_Exit;
  }

  /* ------------- */
  /* The Main Call */

  if (LocaleCompare("-script",argv[1]) == 0) {
    /* Start processing directly from script, no pre-script options
       Replace wand command name with script name
       First argument in the argv array is the script name to read.
    */
    GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
    ProcessScriptOptions(cli_wand,argc,argv,2);
  }
  else {
    /* Normal Command Line, assumes output file as last option */
    ProcessCommandOptions(cli_wand,argc,argv,1);
  }
  /* ------------- */

Magick_Command_Cleanup:
  /* recover original image_info and clean up stacks
     FUTURE: "-reset stacks" option  */
  while (cli_wand->image_list_stack != (Stack *)NULL)
    CLISpecialOperator(cli_wand,")",(const char *)NULL);
  while (cli_wand->image_info_stack != (Stack *)NULL)
    CLISpecialOperator(cli_wand,"}",(const char *)NULL);

  /* assert we have recovered the original structures */
  assert(cli_wand->wand.image_info == image_info);
  assert(cli_wand->wand.exception == exception);

  /* Handle metadata for ImageMagickObject COM object for Windows VBS */
  if (metadata != (char **) NULL) {
    const char
      *format;

    char
      *text;

    format="%w,%h,%m";   // Get this from image_info Option splaytree

    text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
         exception);
    if (text == (char *) NULL)
      ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
           "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
    else {
      (void) ConcatenateString(&(*metadata),text);
      text=DestroyString(text);
    }
  }

Magick_Command_Exit:
  /* Destroy the special CLI Wand */
  cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
  cli_wand->wand.exception = (ExceptionInfo *)NULL;
  cli_wand=DestroyMagickCLI(cli_wand);

  return(IsMagickTrue(exception->severity > ErrorException));
}
Пример #8
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+  P r o c e s s C o m m a n d O p t i o n s                                  %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ProcessCommandOptions() reads and processes arguments in the given
%  command line argument array. The array does not contain the command
%  being processed, only the options.
%
%  The 'process_flags' can be used to control and limit option processing.
%  For example, to only process one option, or how unknown and special options
%  are to be handled, and if the last argument in array is to be regarded as a
%  final image write argument (filename or special coder).
%
%  The format of the ProcessCommandOptions method is:
%
%    int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
%           int index, ProcessOptionFlags process_flags )
%
%  A description of each parameter follows:
%
%    o cli_wand: the main CLI Wand to use.
%
%    o argc: the number of elements in the argument vector.
%
%    o argv: A text array containing the command line arguments.
%
%    o process_flags: What type of arguments will be processed, ignored
%                     or return errors.
%
%    o index: index in the argv array to start processing from
%
% The function returns the index ot the next option to be processed. This
% is really only releven if process_flags contains a ProcessOneOptionOnly
% flag.
%
*/
WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc,
     char **argv, int index )
{
  const char
    *option,
    *arg1,
    *arg2;

  int
    i,
    end,
    count;

  CommandOptionFlags
    option_type;

  assert(argc>=index); /* you may have no arguments left! */
  assert(argv != (char **)NULL);
  assert(argv[index] != (char *)NULL);
  assert(argv[argc-1] != (char *)NULL);
  assert(cli_wand != (MagickCLI *) NULL);
  assert(cli_wand->signature == WandSignature);
  if (cli_wand->wand.debug != MagickFalse)
    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);

  /* define the error location string for use in exceptions
     order of localtion format escapes: filename, line, column */
  cli_wand->location="at %s argument %u";
  cli_wand->filename="CLI";

  end = argc;
  if ( (cli_wand->process_flags & ProcessImpliedWrite) != 0 )
    end--; /* the last arument is an implied write, do not process directly */

  for (i=index; i < end; i += count +1) {
    /* Finished processing one option? */
    if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
      return(i);

    option=argv[i];
    cli_wand->line=i;  /* note the argument for this option */

    { const OptionInfo *option_info = GetCommandOptionInfo(argv[i]);
      count=option_info->type;
      option_type=(CommandOptionFlags) option_info->flags;
#if 0
      (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
            i, argv[i], option_info->mnemonic );
#endif
    }

    if ( option_type == UndefinedOptionFlag ||
         (option_type & NonMagickOptionFlag) != 0 ) {
#if MagickCommandDebug >= 3
      (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option);
#endif
      if ( IfMagickFalse(IsCommandOption(option)) ) {
         if ( (cli_wand->process_flags & ProcessNonOptionImageRead) != 0 )
           /* non-option -- treat as a image read */
           CLISpecialOperator(cli_wand,"-read",option);
         else
           CLIWandException(OptionFatalError,"UnrecognizedOption",option);
         goto next_argument;
      }
      if ( ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
           (LocaleCompare(option,"-script") == 0) ) {
        /* Call Script from CLI, with a filename as a zeroth argument.
           NOTE: -script may need to use 'implict write filename' so it
           must be handled here to prevent 'missing argument' error.
        */
        ProcessScriptOptions(cli_wand,argc,argv,i+1);
        return(argc);  /* Script does not return to CLI -- Yet -- FUTURE */
      }
      CLIWandException(OptionFatalError,"UnrecognizedOption",option);
      goto next_argument;
    }

    if ((i+count) >= end ) {
      CLIWandException(OptionFatalError,"MissingArgument",option);
      if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
        return(end);
      goto next_argument; /* no more arguments unable to proceed */
    }

    arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL;
    arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL;

#if MagickCommandDebug >= 3
    (void) FormatLocaleFile(stderr,
      "CLI %u Option: \"%s\"  Count: %d  Flags: %04x  Args: \"%s\" \"%s\"\n",
          i,option,count,option_type,arg1,arg2);
#endif

    if ( (option_type & DeprecateOptionFlag) != 0 ) {
      CLIWandException(OptionWarning,"DeprecatedOption",option);
      if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
        return(end);
      /* fall through - do the depreciated option */
    }
    if ( (option_type & GenesisOptionFlag) != 0 ) {
      goto next_argument;  /* ignore genesis options */
    }
    if (((option_type & ImageRequiredFlags) != 0 ) &&
        ( cli_wand->wand.images == (Image *)NULL ) ) {
      CLIWandException(OptionError,"NoImagesFound",option);
      goto next_argument;
    }

    if ( (option_type & SpecialOptionFlag) != 0 ) {
      if ( (cli_wand->process_flags & ProcessExitOption) != 0
           && LocaleCompare(option,"-exit") == 0 )
        return(i+count);
      /* handle any other special operators now */
      CLISpecialOperator(cli_wand,option,arg1);
    }

    if ( (option_type & SettingOptionFlags) != 0 ) {
      CLISettingOptionInfo(cli_wand, option, arg1, arg2);
      // FUTURE: Sync individual Settings into images (no SyncImageSettings())
    }
    if ( cli_wand->wand.images != (Image *)NULL )
      SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
          cli_wand->wand.exception);

    if ( (option_type & SimpleOperatorOptionFlag) != 0)
      CLISimpleOperatorImages(cli_wand, option, arg1, arg2);

    if ( (option_type & ListOperatorOptionFlag) != 0 )
      CLIListOperatorImages(cli_wand, option, arg1, arg2);

next_argument:
#if MagickCommandDebug >= 9
    OutputOptions(cli_wand->wand.image_info);
    if ( cli_wand->wand.images != (Image *)NULL ) {
      OutputArtifacts(cli_wand->wand.images);
      OutputProperties(cli_wand->wand.images,cli_wand->wand.exception);
    }
#endif
    if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
      return(i+count);
  }
  assert(i==end);

  if ( (cli_wand->process_flags & ProcessImpliedWrite) == 0 )
    return(end); /* no implied write -- just return to caller */

  assert(end==argc-1); /* end should not include last argument */

  /*
     Implicit Write of images to final CLI argument
  */
  option=argv[i];
  cli_wand->line=i;

#if MagickCommandDebug >= 3
  (void) FormatLocaleFile(stderr, "CLI %d Write File: \"%s\"\n", i, option );
#endif

  /* check that stacks are empty */
  if (cli_wand->image_list_stack != (Stack *)NULL)
    CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
  else if (cli_wand->image_info_stack != (Stack *)NULL)
    CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
  if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
    return(argc);

  /* This is a valid 'do no write' option - no images needed */
  if (LocaleCompare(option,"-exit") == 0 )
    return(argc);  /* just exit, no image write */

  /* If filename looks like an option -- produce an error */
  if (IsCommandOption(option) != MagickFalse) {
    CLIWandException(OptionError,"MissingOutputFilename",option);
    return(argc);
  }

  CLISpecialOperator(cli_wand,"-write",option);
  return(argc);
}
Пример #9
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   P r o c e s s S c r i p t O p t i o n s                                   %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  ProcessScriptOptions() reads options and processes options as they are
%  found in the given file, or pipeline.  The filename to open and read
%  options is given as the 'index' argument of the argument array given.
%
%  Other arguments following index may be read by special script options
%  as settings (strings), images, or as operations to be processed in various
%  ways.   How they are treated is up to the script being processed.
%
%  Note that a script not 'return' to the command line processing, nor can
%  they call (and return from) other scripts. At least not at this time.
%
%  There are no 'ProcessOptionFlags' control flags at this time.
%
%  The format of the ProcessScriptOptions method is:
%
%    void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv,
%               int index)
%
%  A description of each parameter follows:
%
%    o cli_wand: the main CLI Wand to use.
%
%    o argc: the number of elements in the argument vector.
%
%    o argv: A text array containing the command line arguments.
%
%    o index: offset for argc to CLI argumnet count
%
*/
WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv,
     int index)
{
  ScriptTokenInfo
    *token_info;

  CommandOptionFlags
    option_type;

  int
    count;

  char
    *option,
    *arg1,
    *arg2;

  assert(argc>index); /* at least one argument - script name */
  assert(argv != (char **)NULL);
  assert(argv[index] != (char *)NULL);
  assert(argv[argc-1] != (char *)NULL);
  assert(cli_wand != (MagickCLI *) NULL);
  assert(cli_wand->signature == WandSignature);
  if (cli_wand->wand.debug != MagickFalse)
    (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);

  /* open file script or stream, and set up tokenizer */
  token_info = AcquireScriptTokenInfo(argv[index]);
  if (token_info == (ScriptTokenInfo *) NULL) {
    CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",argv[index]);
    return;
  }

  /* define the error location string for use in exceptions
     order of localtion format escapes: filename, line, column */
  cli_wand->location="in \"%s\" at line %u,column %u";
  if ( LocaleCompare("-", argv[index]) == 0 )
    cli_wand->filename="stdin";
  else
    cli_wand->filename=argv[index];

  /* Process Options from Script */
  option = arg1 = arg2 = (char*)NULL;
  while (1) {

    /* Get a option */
    { MagickBooleanType status = GetScriptToken(token_info);
      cli_wand->line=token_info->token_line;
      cli_wand->column=token_info->token_column;
      if( IfMagickFalse(status) )
        break; /* error or end of options */
    }

    /* save option details */
    CloneString(&option,token_info->token);

    { /* get option type and argument count */
      const OptionInfo *option_info = GetCommandOptionInfo(option);
      count=option_info->type;
      option_type=(CommandOptionFlags) option_info->flags;
#if 0
      (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n",
             cli_wand->line, cli_wand->line, option, option_info->mnemonic );
#endif
    }

    /* handle a undefined option - image read? */
    if ( option_type == UndefinedOptionFlag ||
         (option_type & NonMagickOptionFlag) != 0 ) {
#if MagickCommandDebug >= 3
      (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
                  cli_wand->line, cli_wand->line, option);
#endif
      if ( IfMagickFalse(IsCommandOption(option))) {
        /* non-option -- treat as a image read */
        CLISpecialOperator(cli_wand,"-read",option);
        goto next_token;
      }
      if ( LocaleCompare(option,"-script") == 0 ) {
        option_type=SpecialOptionFlag;
        count=1;
        /* fall thru - collect one argument */
      }
      else {
        CLIWandExceptionBreak(OptionFatalError,"UnrecognizedOption",option);
        goto next_token;
      }
    }

    if ( count >= 1 ) {
      if( IfMagickFalse(GetScriptToken(token_info)) )
        CLIWandException(OptionFatalError,"MissingArgument",option);
      CloneString(&arg1,token_info->token);
    }
    else
      CloneString(&arg1,(char *)NULL);

    if ( count >= 2 ) {
      if( IfMagickFalse(GetScriptToken(token_info)) )
        CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option);
      CloneString(&arg2,token_info->token);
    }
    else
      CloneString(&arg2,(char *)NULL);

#if MagickCommandDebug >= 3
    (void) FormatLocaleFile(stderr,
      "Script %u,%u Option: \"%s\"  Count: %d  Flags: %04x  Args: \"%s\" \"%s\"\n",
          cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2);
#endif

    if ( (option_type & GenesisOptionFlag) != 0 ) {
      /* Genesis Options have no place in a magick script */
      CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option);
      goto next_token;
    }
    if ( (option_type & DeprecateOptionFlag) != 0 ) {
      CLIWandException(OptionWarning,"DeprecatedOption",option);
      if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
        break;
      /* fall through - do the depreciated option */
    }
    if (((option_type & ImageRequiredFlags) != 0 ) &&
        ( cli_wand->wand.images == (Image *)NULL ) ) {
      CLIWandException(OptionError,"NoImagesFound",option);
      goto next_token;
    }

    /* handle special script-argument options here */
    //either continue processing command line
    // or making use of the command line options.
    //CLICommandOptions(cli_wand,count+1,argv, MagickScriptArgsFlags);

    /*
      Process Option from file
    */
    if ( (option_type & SpecialOptionFlag) != 0 ) {
      if ( LocaleCompare(option,"-exit") == 0 ) {
        break; /* forced end of script */
      }
      else if ( LocaleCompare(option,"-script") == 0 ) {
        /* FUTURE: call new script from this script */
        CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option);
        goto next_token;
      }
      /* handle any other special operators now */
      CLISpecialOperator(cli_wand,option,arg1);
    }

    if ( (option_type & SettingOptionFlags) != 0 ) {
      CLISettingOptionInfo(cli_wand, option, arg1, arg2);
      // FUTURE: Sync Specific Settings into Image Properities (not global)
    }
    if ( cli_wand->wand.images != (Image *)NULL )
      SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
           cli_wand->wand.exception);

    if ( (option_type & SimpleOperatorOptionFlag) != 0)
      CLISimpleOperatorImages(cli_wand, option, arg1, arg2);

    if ( (option_type & ListOperatorOptionFlag) != 0 )
      CLIListOperatorImages(cli_wand, option, arg1, arg2);

next_token:
#if MagickCommandDebug >= 9
    OutputOptions(cli_wand->wand.image_info);
    if ( cli_wand->wand.images != (Image *)NULL ) {
      OutputArtifacts(cli_wand->wand.images);
      OutputProperties(cli_wand->wand.images,cli_wand->wand.exception);
    }
#endif
    if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
      break;
  }

#if MagickCommandDebug >= 3
  (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
#endif
  switch( token_info->status ) {
    case TokenStatusOK:
    case TokenStatusEOF:
      if (cli_wand->image_list_stack != (Stack *)NULL)
        CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
      else if (cli_wand->image_info_stack != (Stack *)NULL)
        CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
      break;
    case TokenStatusBadQuotes:
      /* Ensure last token has a sane length for error report */
      if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
        token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
        token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
        token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
        token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
      }
      CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
           token_info->token);
      break;
    case TokenStatusMemoryFailed:
      CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
      break;
    case TokenStatusBinary:
      CLIWandException(OptionFatalError,"ScriptIsBinary","");
      break;
  }

  /* Clean up */
  token_info = DestroyScriptTokenInfo(token_info);

  CloneString(&option,(char *)NULL);
  CloneString(&arg1,(char *)NULL);
  CloneString(&arg2,(char *)NULL);

  return;
}