⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmalloc_argv.c

📁 减少内存碎片的malloc分配函数
💻 C
📖 第 1 页 / 共 5 页
字号:
  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 + -