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); } }
/* 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(); } } } }