/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
+   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 == MagickWandSignature);
  if (cli_wand->wand.debug != MagickFalse)
    (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 (IsCommandOption(option) == MagickFalse) {
          /* 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 (GetScriptToken(token_info) == MagickFalse)
          CLIWandException(OptionFatalError,"MissingArgument",option);
        CloneString(&arg1,token_info->token);
      }
      else
        CloneString(&arg1,(char *) NULL);

      if ( count >= 2 ) {
        if (GetScriptToken(token_info) == MagickFalse)
          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 (CLICatchException(cli_wand, MagickFalse) != 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 (cli_wand->wand.debug != MagickFalse)
    (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;
}
Example #2
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;
}