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

📄 expand.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 3 页
字号:
        return 0;      };      break;    };/* * After passing the first character, turn off the explicit match * requirement. */    xplicit = 0;  };/* * To get here the pattern must have been exhausted. If the filename * string matched, then the filename string must also have been * exhausted. */  return *fptr == '\0';}/*....................................................................... * Match a character range expression terminated by an unescaped close * square bracket. * * Input: *  c               int     The character to be matched with the range *                          pattern. *  pattern  const char *   The range pattern to be matched (ie. after the *                          initiating '[' character). *  endp     const char **  On output a pointer to the character following the *                          range expression will be assigned to *endp. * Output: *  return          int     0 - Doesn't match. *                          1 - The character matched. */static int ef_matches_range(int c, const char *pattern, const char **endp){  const char *pptr = pattern;  /* The pointer used to scan the pattern */  int invert = 0;              /* True to invert the sense of the match */  int matched = 0;             /* True if the character matched the pattern *//* * If the first character is a caret, the sense of the match is * inverted and only if the character isn't one of those in the * range, do we say that it matches. */  if(*pptr == '^') {    pptr++;    invert = 1;  };/* * The hyphen is only a special character when it follows the first * character of the range (not including the caret). */  if(*pptr == '-') {    pptr++;    if(c == '-') {      *endp = pptr;      matched = 1;    };/* * Skip other leading '-' characters since they make no sense. */    while(*pptr == '-')      pptr++;  };/* * The hyphen is only a special character when it follows the first * character of the range (not including the caret or a hyphen). */  if(*pptr == ']') {    pptr++;    if(c == ']') {      *endp = pptr;      matched = 1;    };  };/* * Having dealt with the characters that have special meanings at * the beginning of a character range expression, see if the * character matches any of the remaining characters of the range, * up until a terminating ']' character is seen. */  while(!matched && *pptr && *pptr != ']') {/* * Is this a range of characters signaled by the two end characters * separated by a hyphen? */    if(*pptr == '-') {      if(pptr[1] != ']') {        if(c >= pptr[-1] && c <= pptr[1])	  matched = 1;	pptr += 2;      };/* * A normal character to be compared directly. */    } else if(*pptr++ == c) {      matched = 1;    };  };/* * Find the terminating ']'. */  while(*pptr && *pptr != ']')    pptr++;/* * Did we find a terminating ']'? */  if(*pptr == ']') {    *endp = pptr + 1;    return matched ? !invert : invert;  };/* * If the pattern didn't end with a ']' then it doesn't match, regardless * of the value of the required sense of the match. */  *endp = pptr;  return 0;}/*....................................................................... * This is a qsort() comparison function used to sort strings. * * Input: *  v1, v2   void *  Pointers to the two strings to be compared. * Output: *  return    int    -1 -> v1 < v2. *                    0 -> v1 == v2 *                    1 -> v1 > v2 */static int ef_cmp_strings(const void *v1, const void *v2){  char * const *s1 = (char * const *) v1;  char * const *s2 = (char * const *) v2;  return strcmp(*s1, *s2);}/*....................................................................... * Preprocess a path, expanding ~/, ~user/ and $envvar references, using * ef->path as a work buffer, then copy the result into a cache entry, * and return a pointer to this copy. * * Input: *  ef    ExpandFile *  The resource object of the file matcher. *  pathlen      int    The length of the prefix of path[] to be expanded. * Output: *  return      char *  A pointer to a copy of the output path in the *                      cache. On error NULL is returned, and a description *                      of the error is left in ef->errmsg[]. */static char *ef_expand_special(ExpandFile *ef, const char *path, int pathlen){  int spos;      /* The index of the start of the path segment that needs */                 /*  to be copied from path[] to the output pathname. */  int ppos;      /* The index of a character in path[] */  char *pptr;    /* A pointer into the output path */  int escaped;   /* True if the previous character was a '\' */  int i;/* * Clear the pathname buffer. */  _pn_clear_path(ef->path);/* * We need to perform two passes, one to expand environment variables * and a second to do tilde expansion. This caters for the case * where an initial dollar expansion yields a tilde expression. */  escaped = 0;  for(spos=ppos=0; ppos < pathlen; ppos++) {    int c = path[ppos];    if(escaped) {      escaped = 0;    } else if(c == '\\') {      escaped = 1;    } else if(c == '$') {      int envlen;   /* The length of the environment variable */      char *value;  /* The value of the environment variable *//* * Record the preceding unrecorded part of the pathname. */      if(spos < ppos && _pn_append_to_path(ef->path, path + spos, ppos-spos, 0)	 == NULL) {	strcpy(ef->errmsg, "Insufficient memory to expand path");	return NULL;      };/* * Skip the dollar. */      ppos++;/* * Copy the environment variable name that follows the dollar into * ef->envnam[], stopping if a directory separator or end of string * is seen. */      for(envlen=0; envlen<ENV_LEN && ppos < pathlen &&	  strncmp(path + ppos, FS_DIR_SEP, FS_DIR_SEP_LEN); envlen++)	ef->envnam[envlen] = path[ppos++];/* * If the username overflowed the buffer, treat it as invalid (note that * on most unix systems only 8 characters are allowed in a username, * whereas our ENV_LEN is much bigger than that. */      if(envlen >= ENV_LEN) {	strcpy(ef->errmsg, "Environment variable name too long");	return NULL;      };/* * Terminate the environment variable name. */      ef->envnam[envlen] = '\0';/* * Lookup the value of the environment variable. */      value = getenv(ef->envnam);      if(!value) {	const char *fmt = "No expansion found for: $%.*s";	sprintf(ef->errmsg, fmt, ERRLEN - strlen(fmt), ef->envnam);	return NULL;      };/* * Copy the value of the environment variable into the output pathname. */      if(_pn_append_to_path(ef->path, value, -1, 0) == NULL) {	strcpy(ef->errmsg, "Insufficient memory to expand path");	return NULL;      };/* * Record the start of the uncopied tail of the input pathname. */      spos = ppos;    };  };/* * Record the uncopied tail of the pathname. */  if(spos < ppos && _pn_append_to_path(ef->path, path + spos, ppos-spos, 0)     == NULL) {    strcpy(ef->errmsg, "Insufficient memory to expand path");    return NULL;  };/* * If the first character of the resulting pathname is a tilde, * then attempt to substitute the home directory of the specified user. */  pptr = ef->path->name;  if(*pptr == '~' && path[0] != '\\') {    int usrlen;           /* The length of the username following the tilde */    const char *homedir;  /* The home directory of the user */    int homelen;          /* The length of the home directory string */    int plen;             /* The current length of the path */    int skip=0;           /* The number of characters to skip after the ~user *//* * Get the current length of the output path. */    plen = strlen(ef->path->name);/* * Skip the tilde. */    pptr++;/* * Copy the optional username that follows the tilde into ef->usrnam[]. */    for(usrlen=0; usrlen<USR_LEN && *pptr &&	strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN); usrlen++)      ef->usrnam[usrlen] = *pptr++;/* * If the username overflowed the buffer, treat it as invalid (note that * on most unix systems only 8 characters are allowed in a username, * whereas our USR_LEN is much bigger than that. */    if(usrlen >= USR_LEN) {      strcpy(ef->errmsg, "Username too long");      return NULL;    };/* * Terminate the username string. */    ef->usrnam[usrlen] = '\0';/* * Lookup the home directory of the user. */    homedir = _hd_lookup_home_dir(ef->home, ef->usrnam);    if(!homedir) {      strncpy(ef->errmsg, _hd_last_home_dir_error(ef->home), ERRLEN);      ef->errmsg[ERRLEN] = '\0';      return NULL;    };    homelen = strlen(homedir);/* * ~user and ~ are usually followed by a directory separator to * separate them from the file contained in the home directory. * If the home directory is the root directory, then we don't want * to follow the home directory by a directory separator, so we must * erase it. */    if(strcmp(homedir, FS_ROOT_DIR) == 0 &&       strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) {      skip = FS_DIR_SEP_LEN;    };/* * If needed, increase the size of the pathname buffer to allow it * to accomodate the home directory instead of the tilde expression. * Note that pptr may not be valid after this call. */    if(_pn_resize_path(ef->path, plen - usrlen - 1 - skip + homelen)==NULL) {      strcpy(ef->errmsg, "Insufficient memory to expand filename");      return NULL;    };/* * Move the part of the pathname that follows the tilde expression to * the end of where the home directory will need to be inserted. */    memmove(ef->path->name + homelen,	    ef->path->name + 1 + usrlen + skip, plen - usrlen - 1 - skip+1);/* * Write the home directory at the beginning of the string. */    for(i=0; i<homelen; i++)      ef->path->name[i] = homedir[i];  };/* * Copy the result into the cache, and return a pointer to the copy. */  return ef_cache_pathname(ef, ef->path->name, 0);}/*....................................................................... * Return a description of the last path-expansion error that occurred. * * Input: *  ef     ExpandFile *   The path-expansion resource object. * Output: *  return       char *   The description of the last error. */const char *ef_last_error(ExpandFile *ef){  return ef ? ef->errmsg : "NULL ExpandFile argument";}/*....................................................................... * Print out an array of matching files. * * Input: *  result  FileExpansion *   The container of the sorted array of *                            expansions. *  fp               FILE *   The output stream to write to. *  term_width        int     The width of the terminal. * Output: *  return            int     0 - OK. *                            1 - Error. */int ef_list_expansions(FileExpansion *result, FILE *fp, int term_width){  int maxlen;    /* The length of the longest matching string */  int width;     /* The width of a column */  int ncol;      /* The number of columns to list */  int nrow;      /* The number of rows needed to list all of the expansions */  int row,col;   /* The row and column being written to */  int i;/* * Check the arguments. */  if(!result || !fp) {    fprintf(stderr, "ef_list_expansions: NULL argument(s).\n");    return 1;  };/* * Not enough space to list anything? */  if(term_width < 1)    return 0;/* * Work out the maximum length of the matching filenames. */  maxlen = 0;  for(i=0; i<result->nfile; i++) {    int len = strlen(result->files[i]);    if(len > maxlen)      maxlen = len;  };/* * Nothing to list? */  if(maxlen == 0)    return 0;/* * Split the available terminal width into columns of maxlen + 2 characters. */  width = maxlen + 2;  ncol = term_width / width;/* * If the column width is greater than the terminal width, the matches will * just have to overlap onto the next line. */  if(ncol < 1)    ncol = 1;/* * How many rows will be needed? */  nrow = (result->nfile + ncol - 1) / ncol;/* * Print the expansions out in ncol columns, sorted in row order within each * column. */  for(row=0; row < nrow; row++) {    for(col=0; col < ncol; col++) {      int m = col*nrow + row;      if(m < result->nfile) {	const char *filename = result->files[m];	if(fprintf(fp, "%s%-*s%s", filename,		   (int) (ncol > 1 ? maxlen - strlen(filename):0), "",		   col<ncol-1 ? "  " : "\r\n") < 0)	  return 1;      } else {	if(fprintf(fp, "\r\n") < 0)	  return 1;	break;      };    };  };  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -