📄 dmalloc_argv.c
字号:
if (infile == NULL) { *okay_bp = ARGV_FALSE; if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: could not load command-line arguments from: %s\n", argv_program, path); } if (argv_interactive) { (void)exit(EXIT_CODE); } return; } /* get an array of char * */ arg_c = 0; max = ARRAY_INCR; argv = malloc(sizeof(char *) * max); if (argv == NULL) { *okay_bp = ARGV_FALSE; (void)fclose(infile); if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(EXIT_CODE); } return; } argv_p = argv; /* read in the file lines */ while (fgets(line, FILE_LINE_SIZE, infile) != NULL) { /* punch the \n at end of line */ for (line_p = line; *line_p != '\n' && *line_p != '\0'; line_p++) { } *line_p = '\0'; *argv_p = string_copy(line); if (*argv_p == NULL) { *okay_bp = ARGV_FALSE; return; } argv_p++; arg_c++; if (arg_c == max) { max += ARRAY_INCR; argv = realloc(argv, sizeof(char *) * max); if (argv == NULL) { *okay_bp = ARGV_FALSE; (void)fclose(infile); if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: memory error during argument processing\n", argv_program); } if (argv_interactive) { (void)exit(EXIT_CODE); } return; } argv_p = argv + arg_c; } } /* now do the list */ do_list(grid, arg_c, argv, queue_list, queue_head_p, queue_tail_p, okay_bp); /* now free up the list */ for (argv_p = argv; argv_p < argv + arg_c; argv_p++) { free(*argv_p); } free(argv); (void)fclose(infile);}/* * static void do_arg * * DESCRIPTION: * * Process an argument in MATCH_P which looking at GRID. sets okay_p * to FALSE if the argument was not okay. * * RETURNS: * * None. * * ARGUMENTS: * * grid -> Our array of argv_t structures. * * match_p -> Entry in our argv_t structure array that matches the * specified argument. * * close_p -> Pointer to the value closely associated (with an '=') * with this option or NULL if none. * * queue_list <-> Our option queue for storing options to arguments. * * queue_head_p <-> Pointer to integer which will be updated with the * head position in our option queue. * * okay_bp <- Pointer to an integer which is set with 0 if the * arguments specified in the env variable are somehow invalid. */static void do_arg(argv_t *grid, argv_t *match_p, const char *close_p, argv_t **queue_list, int *queue_head_p, int *okay_bp){ if (! argv_multi_accept_b) { /* * have we used this one before? * NOTE: should this be a warning or a non-error altogether? */ if (match_p->ar_type & ARGV_FLAG_USED && (! (match_p->ar_type & ARGV_FLAG_ARRAY)) && ARGV_TYPE(match_p->ar_type) != ARGV_INCR) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, you've already specified the '%c' argument\n", argv_program, USAGE_ERROR_NAME, match_p->ar_short_arg); } *okay_bp = ARGV_FALSE; } } /* we used this argument */ match_p->ar_type |= ARGV_FLAG_USED; /* check arguments that must be OR'd */ if (check_or(grid, match_p) != NOERROR) { /* * don't return here else we might generate an XOR error * because the argument wasn't specified */ *okay_bp = ARGV_FALSE; } /* * If we have a close argument, pass to translate. If it is a * boolean or increment variable, then pass in a value of null * else queue it for needing a value argument. */ if (argv_close_enable_b && close_p != NULL) { if (string_to_value(close_p, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } else if (! HAS_ARG(match_p->ar_type)) { if (string_to_value(NULL, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } else if (argv_close_enable_b && close_p != NULL) { if (string_to_value(close_p, match_p->ar_variable, match_p->ar_type) != NOERROR) { *okay_bp = ARGV_FALSE; } } else { queue_list[*queue_head_p] = match_p; (*queue_head_p)++; }}/* * static int is_number * * DESCRIPTION: * * Examine an argument string to see if it really is a negative number * being passed into a previously specified argument. * * Thanks much to Nick Kisseberth for pointing out this oversight. * * RETURNS: * * 1 if a number otherwise 0. * * ARGUMENTS: * * str - String which may be a number. */static int is_number(const char *str){ const char *str_p; /* empty strings are not numbers */ if (str[0] == '\0') { return 0; } /* * All chars in the string should be number chars for it to be a * number. Yes this will return yes if the argument is "00-" but * we'll chalk this up to user error. */ for (str_p = str; *str_p != '\0'; str_p++) { if (strchr(NUMBER_ARG_CHARS, *str_p) == NULL) { return 0; } } return 1;}/* * static void do_list * * DESCRIPTION: * * Process a list of arguments with our array of argv_t structures * * RETURNS: * * None. * * ARGUMENTS: * * grid - Our array of argv_t structures. * * arg_c - Number of arguments in argv. * * argv - User argument array of character pointers. * * queue_list <-> Our option queue for storing options to arguments. * * queue_head_p <-> Pointer to integer which will be updated with the * head position in our option queue. * * queue_tail_p <-> Pointer to integer which will be updated with the * tail position in our option queue. * * okay_bp - Pointer to an integer which is set with 0 if the * arguments specified in the env variable are somehow invalid. */static void do_list(argv_t *grid, const int arg_c, char **argv, argv_t **queue_list, int *queue_head_p, int *queue_tail_p, int *okay_bp){ argv_t *grid_p, *match_p; int len, char_c, unwant_c = 0; int last_arg_b = ARGV_FALSE; char *close_p = NULL, **arg_p; /* run throught rest of arguments */ for (arg_p = argv; arg_p < argv + arg_c; arg_p++) { /* have we reached the LAST_ARG marker? */ if (strcmp(LAST_ARG, *arg_p) == 0) { if (last_arg_b) { if (argv_last_toggle_b) { last_arg_b = ARGV_FALSE; continue; } } else { last_arg_b = ARGV_TRUE; continue; } } /* are we processing a long option? */ if ((! last_arg_b) && strncmp(LONG_PREFIX, *arg_p, LONG_PREFIX_LENGTH) == 0) { /* * check for close equals marker * * NOTE: duplicated in the short prefix section below. In here otherwise * we process normal args with x=5 instead of just -x=5. */ if (argv_close_enable_b) { close_p = strchr(*arg_p, ARG_EQUALS); /* if we found the special char then punch the null and set pointer */ if (close_p != NULL) { *close_p = '\0'; close_p++; } } /* get length of rest of argument */ len = strlen(*arg_p) - LONG_PREFIX_LENGTH; /* we need more than the prefix */ if (len <= 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, empty long-option prefix '%s'\n", argv_program, USAGE_ERROR_NAME, *arg_p); } *okay_bp = ARGV_FALSE; continue; } match_p = NULL; /* run though long options looking for a match */ for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) { if (grid_p->ar_long_arg == NULL) { continue; } if (strncmp(*arg_p + LONG_PREFIX_LENGTH, grid_p->ar_long_arg, len) == 0) { if (match_p != NULL) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, '%s' might be '%s' or '%s'\n", argv_program, USAGE_ERROR_NAME, *arg_p, grid_p->ar_long_arg, match_p->ar_long_arg); } *okay_bp = ARGV_FALSE; break; } /* record a possible match */ match_p = grid_p; /* don't break, need to see if another one matches */ } } /* if we found a match but quit then we must have found two matches */ if (match_p != NULL && grid_p->ar_short_arg != ARGV_LAST) { continue; } if (match_p != NULL) { (void)do_arg(grid, match_p, close_p, queue_list, queue_head_p, okay_bp); continue; } /* we did not find long-option match */ /* check for special file value */ if (strncmp(FILE_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_close_enable_b && close_p != NULL) { /* open the file and read in the args */ file_args(close_p, grid, queue_list, queue_head_p, queue_tail_p, okay_bp); } else { /* HACK: we enqueue null for the file argument */ queue_list[*queue_head_p] = NULL; (*queue_head_p)++; } continue; } /* check for special usage value */ if (strncmp(USAGE_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0 || strncmp(HELP_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, argv_usage_type); (void)exit(0); } continue; } /* check for special short-usage value */ if (strncmp(USAGE_SHORT_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, ARGV_USAGE_SHORT); (void)exit(0); } continue; } /* check for special long-usage value */ if (strncmp(USAGE_LONG_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, ARGV_USAGE_LONG); (void)exit(0); } continue; } /* check for special long-usage value */ if (strncmp(USAGE_ALL_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { do_usage(grid, ARGV_USAGE_ALL); (void)exit(0); } continue; } /* check for special help value */ if (strncmp(HELP_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { if (argv_error_stream != NULL) { if (argv_help_string == NULL) { (void)fprintf(argv_error_stream, "%s: I'm sorry, no help is available.\n", argv_program); } else { (void)fprintf(argv_error_stream, "%s: %s\n", argv_program, argv_help_string); } } (void)exit(0); } continue; } /* check for special version value */ if (strncmp(VERSION_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { if (argv_error_stream != NULL) { if (argv_version_string == NULL) { (void)fprintf(argv_error_stream, "%s: no version information is available.\n", argv_program); } else { (void)fprintf(argv_error_stream, "%s: %s%s\n", argv_program, VERSION_LABEL, argv_version_string); } } (void)exit(0); } continue; } /* check for display arguments value */ if (strncmp(DISPLAY_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) { if (argv_interactive) { if (argv_error_stream != NULL) { display_variables(grid); } (void)exit(0); } continue; } if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, unknown long option '%s'.\n", argv_program, USAGE_ERROR_NAME, *arg_p); } *okay_bp = ARGV_FALSE; continue; } /* are we processing a short option? */ if ((! last_arg_b) && strncmp(SHORT_PREFIX, *arg_p, SHORT_PREFIX_LENGTH) == 0) { /* * check for close equals marker * * NOTE: duplicated in the long prefix section above. In here otherwise * we process normal args with x=5 instead of just -x=5. */ if (argv_close_enable_b) { close_p = strchr(*arg_p, ARG_EQUALS); /* if we found the special char then punch the null and set pointer */ if (close_p != NULL) { *close_p = '\0'; close_p++; } } /* get length of rest of argument */ len = strlen(*arg_p) - SHORT_PREFIX_LENGTH; /* we need more than the prefix */ if (len <= 0) { if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, empty short-option prefix '%s'\n", argv_program, USAGE_ERROR_NAME, *arg_p); } *okay_bp = ARGV_FALSE; continue; } /* run through the chars in this option */ for (char_c = 0; char_c < len; char_c++) { /* run through the arg list looking for a match */ for (match_p = grid; match_p->ar_short_arg != ARGV_LAST; match_p++) { if (match_p->ar_short_arg == (*arg_p)[SHORT_PREFIX_LENGTH + char_c]) { break; } } /* did we not find argument? */ if (match_p->ar_short_arg == ARGV_LAST) { /* check for special usage value */ if ((*arg_p)[SHORT_PREFIX_LENGTH + char_c] == USAGE_CHAR_ARG) { if (argv_interactive) { do_usage(grid, argv_usage_type); (void)exit(0); } continue; } /* * allow values with negative signs if we are at the start * of an argument list, and if the argument is a number, and * we already have a variable looking for a value. Thanks * to Nick Kisseberth for pointing out this oversight. */ if (char_c == 0 && is_number(*arg_p) && *queue_head_p > *queue_tail_p) { match_p = queue_list[*queue_tail_p]; /* * NOTE: we don't advance the queue tail here unless we * find out that we can use it below */ switch (ARGV_TYPE(match_p->ar_type)) { case ARGV_SHORT: case ARGV_INT: case ARGV_LONG: case ARGV_FLOAT: case ARGV_DOUBLE: string_to_value(*arg_p, match_p->ar_variable, match_p->ar_type); char_c = len; /* we actually used it so we advance the queue tail position */ (*queue_tail_p)++; continue; break; } } /* create an error string */ if (argv_error_stream != NULL) { (void)fprintf(argv_error_stream, "%s: %s, unknown short option '%s%c'.\n", argv_program, USAGE_ERROR_NAME, SHORT_PRE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -