Beispiel #1
0
void
read_args_file(const char *infile)
{   char *line;
    FILE *fp = fopen(infile,"r");

    if(fp == NULL){
        fprintf(GlobalState.logfile,"Cannot open %s for reading.\n",infile);
        exit(1);
    }
    else{
        ArgType linetype = NO_ARGUMENT_MATCH;
        ArgType nexttype;
        while((line = read_line(fp)) != NULL){
            if(blank_line(line)){
                (void) free(line);
                continue;
            }
            nexttype = classify_arg(line);
            if(nexttype == NO_ARGUMENT_MATCH){
                if(*line == argument_prefix[0]){
                    /* Treat the line as a source file name. */
                    add_filename_to_source_list(&line[1],NORMALFILE);
                }
                else if(linetype != NO_ARGUMENT_MATCH){
                    /* Handle the line. */
                    switch(linetype){
                        case MOVES_ARGUMENT:
                            add_textual_variation_from_line(line);
                            break;
                        case POSITIONS_ARGUMENT:
                            add_positional_variation_from_line(line);
                            break;
                        case TAGS_ARGUMENT:
                            process_tag_line(infile,line);
                            break;
                        case TAG_ROSTER_ARGUMENT:
                            process_roster_line(line);
                            break;
                        case ENDINGS_ARGUMENT:
                            process_ending_line(line);
                            (void) free(line);
                            break;
                        default:
                            fprintf(GlobalState.logfile,
                                    "Internal error: unknown linetype %d in read_args_file\n",
                                    linetype);
                            (void) free(line);
                            exit(-1);
                    }
                }
                else{
                    /* It should have been a line applying to the
                     * current linetype.
                     */
                    fprintf(GlobalState.logfile,
                        "Missing argument type for line %s in the argument file.\n",
                        line);
                    exit(1);
                }
            }
            else{
                switch(nexttype){
                        /* Arguments with a possible additional
                         * argument value.
                         * All of these apply only to the current
                         * line in the argument file.
                         */
                    case WRITE_TO_OUTPUT_FILE_ARGUMENT:
                    case APPEND_TO_OUTPUT_FILE_ARGUMENT:
                    case WRITE_TO_LOG_FILE_ARGUMENT:
                    case APPEND_TO_LOG_FILE_ARGUMENT:
                    case DUPLICATES_FILE_ARGUMENT:
                    case USE_ECO_FILE_ARGUMENT:
                    case CHECK_FILE_ARGUMENT:
                    case FILE_OF_FILES_ARGUMENT:
                    case BOUNDS_ARGUMENT:
                    case GAMES_PER_FILE_ARGUMENT:
                    case ECO_OUTPUT_LEVEL_ARGUMENT:
                    case FILE_OF_ARGUMENTS_ARGUMENT:
                    case NON_MATCHING_GAMES_ARGUMENT:
                    case TAG_EXTRACTION_ARGUMENT:
                    case LINE_WIDTH_ARGUMENT:
                    case OUTPUT_FORMAT_ARGUMENT:
                        process_argument(line[argument_prefix_len],
                                         &line[argument_prefix_len+1]);
                        linetype = NO_ARGUMENT_MATCH;
                        break;
                    case LONG_FORM_ARGUMENT:
			{
			    char *arg = &line[argument_prefix_len+1];
			    char *space = strchr(arg, ' ');
			    if(space != NULL) {
				/* We need to drop an associated value from arg. */
				int arglen = space - arg;
				char *just_arg = (char *) MallocOrDie(arglen + 1);
				strncpy(just_arg, arg, arglen);
				just_arg[arglen] = '\0';
				process_long_form_argument(just_arg,
							   skip_leading_spaces(space));
			    }
			    else {
				process_long_form_argument(arg, "");
				linetype = NO_ARGUMENT_MATCH;
			    }
			}
                        break;

                        /* Arguments with no additional
                         * argument value.
                         * All of these apply only to the current
                         * line in the argument file.
                         */
                    case SEVEN_TAG_ROSTER_ARGUMENT:
                    case HELP_ARGUMENT:
                    case ALTERNATIVE_HELP_ARGUMENT:
                    case DONT_KEEP_COMMENTS_ARGUMENT:
                    case DONT_KEEP_DUPLICATES_ARGUMENT:
                    case DONT_MATCH_PERMUTATIONS_ARGUMENT:
                    case DONT_KEEP_NAGS_ARGUMENT:
                    case OUTPUT_FEN_STRING_ARGUMENT:
                    case CHECK_ONLY_ARGUMENT:
                    case KEEP_SILENT_ARGUMENT:
                    case USE_SOUNDEX_ARGUMENT:
                    case MATCH_CHECKMATE_ARGUMENT:
                    case SUPPRESS_ORIGINALS_ARGUMENT:
                    case DONT_KEEP_VARIATIONS_ARGUMENT:
                    case USE_VIRTUAL_HASH_TABLE_ARGUMENT:
                        process_argument(line[argument_prefix_len],"");
                        linetype = NO_ARGUMENT_MATCH;
                        break;

                        /* Arguments whose values persist beyond
                         * the current line.
                         */
                    case MOVES_ARGUMENT:
                    case POSITIONS_ARGUMENT:
                    case ENDINGS_ARGUMENT:
                    case TAGS_ARGUMENT:
                    case TAG_ROSTER_ARGUMENT:
                        process_argument(line[argument_prefix_len],
                                         &line[argument_prefix_len+1]);
                        /* Apply this type to subsequent lines. */
                        linetype = nexttype;
                        break;
                    default:
                        linetype = nexttype;
                        break;
                }
                (void) free(line);
            }
        }
        (void) fclose(fp);
    }
}
Beispiel #2
0
/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
   Any error from the parsers is returned, and *ARGP_EBADKEY indicates
   whether a value of EBADKEY is due to an unrecognized argument (which is
   generally not fatal).  */
static error_t
parser_parse_next (struct parser *parser, int *arg_ebadkey)
{
  if (parser->state.quoted && parser->state.next < parser->state.quoted)
    /* The next argument pointer has been moved to before the quoted
       region, so pretend we never saw the quoting `--', and start
       looking for options again. If the `--' is still there we'll just
       process it one more time. */
    parser->state.quoted = parser->args_only = 0;

  /* Give FIRST_NONOPT & LAST_NONOPT rational values if NEXT has been
     moved back by the user (who may also have changed the arguments).  */
  if (parser->last_nonopt > parser->state.next)
    parser->last_nonopt = parser->state.next;
  if (parser->first_nonopt > parser->state.next)
    parser->first_nonopt = parser->state.next;

  if (parser->nextchar)
    /* Deal with short options. */
    {
      struct group *group;
      char c;
      const struct argp_option *option;
      char *value = NULL;;

      assert(!parser->args_only);

      c = *parser->nextchar++;

      option = find_short_option(parser, c, &group);
      if (!option)
	{
	  if (parser->posixly_correct)
	    /* 1003.2 specifies the format of this message.  */
	    fprintf (parser->state.err_stream,
		     dgettext(parser->state.root_argp->argp_domain,
			      "%s: illegal option -- %c\n"),
		     parser->state.name, c);
	  else
	    fprintf (parser->state.err_stream,
		     dgettext(parser->state.root_argp->argp_domain,
			      "%s: invalid option -- %c\n"),
		     parser->state.name, c);

	  *arg_ebadkey = 0;
	  return EBADKEY;
	}

      if (!*parser->nextchar)
	parser->nextchar = NULL;

      if (option->arg)
	{
	  value = parser->nextchar;
	  parser->nextchar = NULL;

	  if (!value
	      && !(option->flags & OPTION_ARG_OPTIONAL))
	    /* We need an mandatory argument. */
	    {
	      if (parser->state.next == parser->state.argc)
		/* Missing argument */
		{
		  /* 1003.2 specifies the format of this message.  */
		  fprintf (parser->state.err_stream,
			   dgettext(parser->state.root_argp->argp_domain,
				    "%s: option requires an argument -- %c\n"),
			   parser->state.name, c);

		  *arg_ebadkey = 0;
		  return EBADKEY;
		}
	      value = parser->state.argv[parser->state.next++];
	    }
	}
      return group_parse(group, &parser->state,
			 option->key, value);
    }
  else
    /* Advance to the next ARGV-element.  */
    {
      if (parser->args_only)
	{
	  *arg_ebadkey = 1;
	  if (parser->state.next >= parser->state.argc)
	    /* We are done: */
	    return EBADKEY;
	  else
	    return parser_parse_arg(parser,
				    parser->state.argv[parser->state.next]);
	}

      if (parser->state.next >= parser->state.argc)
	/* Almost done. If there are non-options that we skipped
	   previously, we should process them now. */
	{
	  *arg_ebadkey = 1;
	  if (parser->first_nonopt != parser->last_nonopt)
	    {
	      exchange(parser);

	      /* Start processing the arguments we skipped previously: */
	      parser->state.next = parser->first_nonopt;

	      parser->first_nonopt = parser->last_nonopt = 0;

	      parser->args_only = 1;
	      return 0;
	    }
	  else
	    /* Indicate that we are really done. */
	    return EBADKEY;
	}
      else
	/* Look for options. */
	{
	  char *arg = parser->state.argv[parser->state.next];

	  char *optstart;
	  enum arg_type token = classify_arg(parser, arg, &optstart);

	  switch (token)
	    {
	    case ARG_ARG:
	      switch (parser->ordering)
		{
		case PERMUTE:
                  if (parser->first_nonopt == parser->last_nonopt) {
		    /* Skipped sequence is empty; start a new one: */
		    parser->first_nonopt = parser->last_nonopt = parser->state.next;
		  } else if (parser->last_nonopt != parser->state.next) {
                    /* We have a non-empty skipped sequence, and we are not
                     * at the end-point, so move it. */
		    exchange(parser);
                  }

		  assert(parser->last_nonopt == parser->state.next);

		  /* Skip this argument for now: */
		  parser->state.next++;
		  parser->last_nonopt = parser->state.next;

		  return 0;

		case REQUIRE_ORDER:
		  /* Implicit quote before the first argument. */
		   parser->args_only = 1;
		   return 0;

		case RETURN_IN_ORDER:
		  *arg_ebadkey = 1;
		  return parser_parse_arg(parser, arg);

		default:
		  abort();
		}
	    case ARG_QUOTE:
	      /* Skip it, then exchange with any previous non-options: */
	      parser->state.next++;
	      assert(parser->last_nonopt != parser->state.next);

	      if (parser->first_nonopt != parser->last_nonopt)
		{
		  exchange(parser);

		  /* Start processing the skipped and the quoted
		     arguments. */

		  parser->state.quoted = parser->state.next = parser->first_nonopt;

		  /* Also empty the skipped-list, to avoid confusion
		     if the user resets the next pointer. */
		  parser->first_nonopt = parser->last_nonopt = 0;
		}
	      else
		parser->state.quoted = parser->state.next;

	      parser->args_only = 1;
	      return 0;

	    case ARG_LONG_ONLY_OPTION:
	    case ARG_LONG_OPTION:
	      {
		struct group *group;
		const struct argp_option *option;
		char *value;

		parser->state.next++;
		option = find_long_option(parser, optstart, &group);

		if (!option)
		  {
		    /* NOTE: This includes any "=something" in the output: */
		    fprintf(parser->state.err_stream,
			    dgettext(parser->state.root_argp->argp_domain,
                                     "%s: unrecognized option `%s'\n"),
			    parser->state.name, arg);
		    *arg_ebadkey = 0;
		    return EBADKEY;
		  }

		value = strchr(optstart, '=');
		if (value)
		  value++;

		if (value && !option->arg)
		  /* Unexpected argument. */
		  {
		    if (token == ARG_LONG_OPTION)
		      /* --option */
		      fprintf(parser->state.err_stream,
			      dgettext(parser->state.root_argp->argp_domain,
                                       "%s: option `--%s' does NOT allow an argument\n"),
			      parser->state.name, option->name);
		    else
		      /* +option or -option */
		      fprintf(parser->state.err_stream,
			      dgettext(parser->state.root_argp->argp_domain,
                                       "%s: option `%c%s' does NOT allow an argument\n"),
			      parser->state.name, arg[0], option->name);

		    *arg_ebadkey = 0;
		    return EBADKEY;
		  }

		if (option->arg && !value
		    && !(option->flags & OPTION_ARG_OPTIONAL))
		  /* We need an mandatory argument. */
		  {
		    if (parser->state.next == parser->state.argc)
		      /* Missing argument */
		      {
			if (token == ARG_LONG_OPTION)
			  /* --option */
			  fprintf (parser->state.err_stream,
				   dgettext(parser->state.root_argp->argp_domain,
					    "%s: option `--%s' requires an argument\n"),
				 parser->state.name, option->name);
			else
			  /* +option or -option */
			  fprintf (parser->state.err_stream,
				   dgettext(parser->state.root_argp->argp_domain,
					    "%s: option `%c%s' requires an argument\n"),
				   parser->state.name, arg[0], option->name);

			*arg_ebadkey = 0;
			return EBADKEY;
		      }

		    value = parser->state.argv[parser->state.next++];
		  }
		*arg_ebadkey = 0;
		return group_parse(group, &parser->state,
				   option->key, value);
	      }
	    case ARG_SHORT_OPTION:
	      parser->state.next++;
	      parser->nextchar = optstart;
	      return 0;

	    default:
	      abort();
	    }
	}
    }
}