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

📄 expand.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Sort the pathnames that matched. */    qsort(ef->result.files, ef->result.nfile, sizeof(ef->result.files[0]),	  ef_cmp_strings);  };/* * Return the result container. */  return &ef->result;}/*....................................................................... * Attempt to recursively match the given pattern with the contents of * the current directory, descending sub-directories as needed. * * Input: *  ef      ExpandFile *  The pathname expansion resource object. *  dr       DirReader *  The directory reader object of the directory *                        to be searched. *  pattern const char *  The pattern to match with files in the current *                        directory. *  separate       int    When appending a filename from the specified *                        directory to ef->pathname, insert a directory *                        separator between the existing pathname and *                        the filename, unless separate is zero. * Output: *  return         int    0 - OK. *                        1 - Error. */static int ef_match_relative_pathname(ExpandFile *ef, DirReader *dr,				       const char *pattern, int separate){  const char *nextp;  /* The pointer to the character that follows the part */                      /*  of the pattern that is to be matched with files */                      /*  in the current directory. */  char *file;         /* The name of the file being matched */  int pathlen;        /* The length of ef->pathname[] on entry to this */                      /*  function *//* * Record the current length of the pathname string recorded in * ef->pathname[]. */  pathlen = strlen(ef->path->name);/* * Get a pointer to the character that follows the end of the part of * the pattern that should be matched to files within the current directory. * This will either point to a directory separator, or to the '\0' terminator * of the pattern string. */  for(nextp=pattern; *nextp && strncmp(nextp, FS_DIR_SEP, FS_DIR_SEP_LEN) != 0;      nextp++)    ;/* * Read each file from the directory, attempting to match it to the * current pattern. */  while((file=_dr_next_file(dr)) != NULL) {/* * Does the latest file match the pattern up to nextp? */    if(ef_string_matches_pattern(file, pattern, file[0]=='.', nextp)) {/* * Append the new directory entry to the current matching pathname. */      if((separate && _pn_append_to_path(ef->path, FS_DIR_SEP, -1, 0)==NULL) ||	 _pn_append_to_path(ef->path, file, -1, 0)==NULL) {	strcpy(ef->errmsg, "Insufficient memory to record path");	return 1;      };/* * If we have reached the end of the pattern, record the accumulated * pathname in the list of matching files. */      if(*nextp == '\0') {	if(ef_record_pathname(ef, ef->path->name, 0))	  return 1;/* * If the matching directory entry is a subdirectory, and the * next character of the pattern is a directory separator, * recursively call the current function to scan the sub-directory * for matches. */      } else if(_pu_path_is_dir(ef->path->name) &&		strncmp(nextp, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) {/* * If the pattern finishes with the directory separator, then * record the pathame as matching. */	if(nextp[FS_DIR_SEP_LEN] == '\0') {	  if(ef_record_pathname(ef, ef->path->name, 0))	    return 1;/* * Match files within the directory. */	} else {	  DirNode *subdnode = ef_open_dir(ef, ef->path->name);	  if(subdnode) {	    if(ef_match_relative_pathname(ef, subdnode->dr,					   nextp+FS_DIR_SEP_LEN, 1)) {	      subdnode = ef_close_dir(ef, subdnode);	      return 1;	    };	    subdnode = ef_close_dir(ef, subdnode);	  };	};      };/* * Remove the latest filename from the pathname string, so that * another matching file can be appended. */      ef->path->name[pathlen] = '\0';    };  };  return 0;}/*....................................................................... * Record a new matching filename. * * Input: *  ef        ExpandFile *  The filename-match resource object. *  pathname  const char *  The pathname to record. *  remove_escapes   int    If true, remove backslash escapes in the *                          recorded copy of the pathname. * Output: *  return           int     0 - OK. *                           1 - Error (ef->errmsg will contain a *                                      description of the error). */static int ef_record_pathname(ExpandFile *ef, const char *pathname,			      int remove_escapes){  char *copy;          /* The recorded copy of pathname[] *//* * Attempt to make a copy of the pathname in the cache. */  copy = ef_cache_pathname(ef, pathname, remove_escapes);  if(!copy)    return 1;/* * If there isn't room to record a pointer to the recorded pathname in the * array of files, attempt to extend the array. */  if(ef->result.nfile + 1 > ef->files_dim) {    int files_dim = ef->files_dim + MATCH_BLK_FACT;    char **files = (char **) realloc(ef->result.files,				     files_dim * sizeof(files[0]));    if(!files) {      sprintf(ef->errmsg,	      "Insufficient memory to record all of the matching filenames");      return 1;    };    ef->result.files = files;    ef->files_dim = files_dim;  };/* * Record a pointer to the new match. */  ef->result.files[ef->result.nfile++] = copy;  return 0;}/*....................................................................... * Record a pathname in the cache. * * Input: *  ef       ExpandFile *  The filename-match resource object. *  pathname       char *  The pathname to record. *  remove_escapes  int    If true, remove backslash escapes in the *                         copy of the pathname. * Output: *  return         char *  The pointer to the copy of the pathname. *                         On error NULL is returned and a description *                         of the error is left in ef->errmsg[]. */static char *ef_cache_pathname(ExpandFile *ef, const char *pathname,			       int remove_escapes){  char *copy = _sg_store_string(ef->sg, pathname, remove_escapes);  if(!copy)    strcpy(ef->errmsg, "Insufficient memory to store pathname");  return copy;}/*....................................................................... * Clear the results of the previous expansion operation, ready for the * next. * * Input: *  ef    ExpandFile *  The pathname expansion resource object. */static void ef_clear_files(ExpandFile *ef){  _clr_StringGroup(ef->sg);  _pn_clear_path(ef->path);  ef->result.exists = 0;  ef->result.nfile = 0;  ef->errmsg[0] = '\0';  return;}/*....................................................................... * Get a new directory reader object from the cache. * * Input: *  ef        ExpandFile *  The pathname expansion resource object. *  pathname  const char *  The pathname of the directory. * Output: *  return       DirNode *  The cache entry of the new directory reader, *                          or NULL on error. On error, ef->errmsg will *                          contain a description of the error. */static DirNode *ef_open_dir(ExpandFile *ef, const char *pathname){  char *errmsg = NULL;  /* An error message from a called function */  DirNode *node;        /* The cache node used *//* * Get the directory reader cache. */  DirCache *cache = &ef->cache;/* * Extend the cache if there are no free cache nodes. */  if(!cache->next) {    node = (DirNode *) _new_FreeListNode(cache->mem);    if(!node) {      sprintf(ef->errmsg, "Insufficient memory to open a new directory");      return NULL;    };/* * Initialize the cache node. */    node->next = NULL;    node->prev = NULL;    node->dr = NULL;/* * Allocate a directory reader object. */    node->dr = _new_DirReader();    if(!node->dr) {      sprintf(ef->errmsg, "Insufficient memory to open a new directory");      node = (DirNode *) _del_FreeListNode(cache->mem, node);      return NULL;    };/* * Append the node to the cache list. */    node->prev = cache->tail;    if(cache->tail)      cache->tail->next = node;    else      cache->head = node;    cache->next = cache->tail = node;  };/* * Get the first unused node, but don't remove it from the list yet. */  node = cache->next;/* * Attempt to open the specified directory. */  if(_dr_open_dir(node->dr, pathname, &errmsg)) {    strncpy(ef->errmsg, errmsg, ERRLEN);    ef->errmsg[ERRLEN] = '\0';    return NULL;  };/* * Now that we have successfully opened the specified directory, * remove the cache node from the list, and relink the list around it. */  cache->next = node->next;  if(node->prev)    node->prev->next = node->next;  else    cache->head = node->next;  if(node->next)    node->next->prev = node->prev;  else    cache->tail = node->prev;  node->next = node->prev = NULL;/* * Return the successfully initialized cache node to the caller. */  return node;}/*....................................................................... * Return a directory reader object to the cache, after first closing * the directory that it was managing. * * Input: *  ef    ExpandFile *  The pathname expansion resource object. *  node     DirNode *  The cache entry of the directory reader, as returned *                      by ef_open_dir(). * Output: *  return   DirNode *  The deleted DirNode (ie. allways NULL). */static DirNode *ef_close_dir(ExpandFile *ef, DirNode *node){/* * Get the directory reader cache. */  DirCache *cache = &ef->cache;/* * Close the directory. */  _dr_close_dir(node->dr);/* * Return the node to the tail of the cache list. */  node->next = NULL;  node->prev = cache->tail;  if(cache->tail)    cache->tail->next = node;  else    cache->head = cache->tail = node;  if(!cache->next)    cache->next = node;  return NULL;}/*....................................................................... * Return non-zero if the specified file name matches a given glob * pattern. * * Input: *  file     const char *  The file-name component to be matched to the pattern. *  pattern  const char *  The start of the pattern to match against file[]. *  xplicit         int    If non-zero, the first character must be matched *                         explicitly (ie. not with a wildcard). *  nextp    const char *  The pointer to the the character following the *                         end of the pattern in pattern[]. * Output: *  return    int          0 - Doesn't match. *                         1 - The file-name string matches the pattern. */static int ef_string_matches_pattern(const char *file, const char *pattern,				      int xplicit, const char *nextp){  const char *pptr = pattern; /* The pointer used to scan the pattern */  const char *fptr = file;    /* The pointer used to scan the filename string *//* * Match each character of the pattern in turn. */  while(pptr < nextp) {/* * Handle the next character of the pattern. */    switch(*pptr) {/* * A match zero-or-more characters wildcard operator. */    case '*':/* * Skip the '*' character in the pattern. */      pptr++;/* * If wildcards aren't allowed, the pattern doesn't match. */      if(xplicit)	return 0;/* * If the pattern ends with a the '*' wildcard, then the * rest of the filename matches this. */      if(pptr >= nextp)	return 1;/* * Using the wildcard to match successively longer sections of * the remaining characters of the filename, attempt to match * the tail of the filename against the tail of the pattern. */      for( ; *fptr; fptr++) {	if(ef_string_matches_pattern(fptr, pptr, 0, nextp))	  return 1;      };      return 0; /* The pattern following the '*' didn't match */      break;/* * A match-one-character wildcard operator. */    case '?':/* * If there is a character to be matched, skip it and advance the * pattern pointer. */      if(!xplicit && *fptr) {        fptr++;        pptr++;/* * If we hit the end of the filename string, there is no character * matching the operator, so the string doesn't match. */      } else {        return 0;      };      break;/* * A character range operator, with the character ranges enclosed * in matching square brackets. */    case '[':      if(xplicit || !ef_matches_range(*fptr++, ++pptr, &pptr))        return 0;      break;/* * A backslash in the pattern prevents the following character as * being seen as a special character. */    case '\\':      pptr++;      /* Note fallthrough to default *//* * A normal character to be matched explicitly. */    default:      if(*fptr == *pptr) {        fptr++;        pptr++;      } else {

⌨️ 快捷键说明

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