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

📄 pcache.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 4 页
字号:
 * scan it for files of interest. */    if(node->relative) {      rst_CacheMem(node->mem);      if(pca_scan_dir(pc, node->dir, node->mem) < 1)	continue;      node->files = node->mem->files;      node->nfile = node->mem->nfiles;    };/* * If needed, make a copy of the file-name being matched, with * escapes removed. Note that we need to do this anew every loop * iteration, because the above call to pca_scan_dir() uses * pc->path. */    prefix = pca_prepare_prefix(pc, start_path, prefix_len, ppc->escaped);    if(!prefix)      return 1;/* * The directory entries are sorted, so we can perform a binary * search for an instance of the prefix being searched for. */    bot = 0;    top = node->nfile - 1;    while(top >= bot) {      int mid = (top + bot)/2;      int test = strncmp(node->files[mid]+1, prefix, prefix_len);      if(test > 0)	top = mid - 1;      else if(test < 0)	bot = mid + 1;      else {	top = bot = mid;	break;      };    };/* * If we found a match, look to see if any of its neigbors also match. */    if(top == bot) {      while(--bot >= 0 && strncmp(node->files[bot]+1, prefix, prefix_len) == 0)	;      while(++top < node->nfile &&	    strncmp(node->files[top]+1, prefix, prefix_len) == 0)	;/* * We will have gone one too far in each direction. */      bot++;      top--;/* * Add the completions to the list after checking them against the * callers requirements. */      for( ; bot<=top; bot++) {	char *match = node->files[bot];/* * Form the full pathname of the file. */	_pn_clear_path(pc->path);	if(_pn_append_to_path(pc->path, node->dir, -1, 0) == NULL ||	   _pn_append_to_path(pc->path, match+1, -1, 0) == NULL) {	  strcpy(pc->errmsg, "Insufficient memory to complete file name");	  return 1;	};/* * Should the file be included in the list of completions? */	if(!pc->check_fn || match[0] == PCA_F_WANTED ||	   (match[0]==PCA_F_ENIGMA && pc->check_fn(pc->data, pc->path->name))) {	  match[0] = PCA_F_WANTED;/* * Copy the completion suffix into the work pathname pc->path->name, * adding backslash escapes if needed. */	  if(pca_prepare_suffix(pc, match + 1 + prefix_len,				ppc->escaped))	    return 1;/* * Record the completion. */	  if(cpl_add_completion(cpl, line, word_start, word_end, pc->path->name,				"", " "))	    return 1;/* * The file was rejected by the application. */	} else {	  match[0] = PCA_F_IGNORE;	};      };    };  };/* * We now need to search for subdirectories of the current directory which * have matching prefixes. First, if needed, make a copy of the word being * matched, with escapes removed. */  prefix = pca_prepare_prefix(pc, start_path, prefix_len, ppc->escaped);  if(!prefix)    return 1;/* * Now open the current directory. */  if(_dr_open_dir(pc->dr, FS_PWD, NULL))    return 0;/* * Scan the current directory for sub-directories whos names start with * the prefix that we are completing. */  while((filename = _dr_next_file(pc->dr))) {/* * Does the latest filename match the prefix, and is it a directory? */    if(strncmp(filename, prefix, prefix_len) == 0 && _pu_path_is_dir(filename)){/* * Record the completion. */      if(pca_prepare_suffix(pc, filename + prefix_len, ppc->escaped) ||	 cpl_add_completion(cpl, line, word_start, word_end, pc->path->name,			    FS_DIR_SEP, FS_DIR_SEP))	return 1;/* * The prefix in pc->path->name will have been overwritten by * pca_prepare_suffix(). Restore it here. */      prefix = pca_prepare_prefix(pc, start_path, prefix_len, ppc->escaped);      if(!prefix)	return 1;    };  };  _dr_close_dir(pc->dr);  return 0;}/*....................................................................... * Using the work buffer pc->path, make a suitably escaped copy of a * given completion suffix, ready to be passed to cpl_add_completion(). * * Input: *  pc      PathCache *  The filename cache resource object. *  suffix       char *  The suffix to be copied. *  add_escapes   int    If true, escape special characters. * Output: *  return        int    0 - OK. *                       1 - Error. */static int pca_prepare_suffix(PathCache *pc, const char *suffix,			      int add_escapes){  const char *sptr; /* A pointer into suffix[] */  int nbsl;         /* The number of backslashes to add to the suffix */  int i;/* * How long is the suffix? */  int suffix_len = strlen(suffix);/* * Clear the work buffer. */  _pn_clear_path(pc->path);/* * Count the number of backslashes that will have to be added to * escape spaces, tabs, backslashes and wildcard characters. */  nbsl = 0;  if(add_escapes) {    for(sptr = suffix; *sptr; sptr++) {      switch(*sptr) {      case ' ': case '\t': case '\\': case '*': case '?': case '[':	nbsl++;	break;      };    };  };/* * Arrange for the output path buffer to have sufficient room for the * both the suffix and any backslashes that have to be inserted. */  if(_pn_resize_path(pc->path, suffix_len + nbsl) == NULL) {    strcpy(pc->errmsg, "Insufficient memory to complete file name");    return 1;  };/* * If the suffix doesn't need any escapes, copy it directly into the * work buffer. */  if(nbsl==0) {    strcpy(pc->path->name, suffix);  } else {/* * Make a copy with special characters escaped? */    if(nbsl > 0) {      const char *src = suffix;      char *dst = pc->path->name;      for(i=0; i<suffix_len; i++) {	switch(*src) {	case ' ': case '\t': case '\\': case '*': case '?': case '[':	  *dst++ = '\\';	};	*dst++ = *src++;      };      *dst = '\0';    };  };  return 0;}/*....................................................................... * Return non-zero if the specified string appears to start with a pathname. * * Input: *  prefix  const char *  The filename prefix to check. *  prefix_len     int    The length of the prefix. * Output: *  return         int    0 - Doesn't start with a path name. *                        1 - Does start with a path name. */static int cpa_cmd_contains_path(const char *prefix, int prefix_len){  int i;/* * If the filename starts with a ~, then this implies a ~username * expression, which constitutes a pathname. */  if(*prefix == '~')    return 1;/* * If the filename starts with the root directory, then it obviously * starts with a pathname. */  if(prefix_len >= FS_ROOT_DIR_LEN &&      strncmp(prefix, FS_ROOT_DIR, FS_ROOT_DIR_LEN) == 0)    return 1;/* * Search the prefix for directory separators, returning as soon as * any are found, since their presence indicates that the filename * starts with a pathname specification (valid or otherwise). */  for(i=0; i<prefix_len; i++) {    if(prefix_len - i >= FS_DIR_SEP_LEN &&       strncmp(prefix + i, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0)      return 1;  };/* * The file name doesn't appear to start with a pathname specification. */  return 0;}/*....................................................................... * If needed make a new copy of the prefix being matched, in pc->path->name, * but with escapes removed. If no escapes are to be removed, simply return * the original prefix string. * * Input: *  pc      PathCache *   The cache being searched. *  prefix const char *   The prefix to be processed. *  prefix_len size_t     The length of the prefix. *  escaped       int     If true, return a copy with escapes removed. * Output: *  return const char *   The prepared prefix, or NULL on error, in *                        which case an error message will have been *                        left in pc->errmsg. */static const char *pca_prepare_prefix(PathCache *pc, const char *prefix,				      size_t prefix_len, int escaped){/* * Make a copy with escapes removed? */  if(escaped) {    _pn_clear_path(pc->path);    if(_pn_append_to_path(pc->path, prefix, prefix_len, 1) == NULL) {      strcpy(pc->errmsg, "Insufficient memory to complete filename");      return NULL;    };    return pc->path->name;  };  return prefix;}/*....................................................................... * If backslashes in the filename should be treated as literal * characters, call the following function with literal=1. Otherwise * the default is to treat them as escape characters, used for escaping * spaces etc.. * * Input: *  ppc    PcaPathConf *  The pca_path_completions() configuration object *                        to be configured. *  literal        int    Pass non-zero here to enable literal interpretation *                        of backslashes. Pass 0 to turn off literal *                        interpretation. */void ppc_literal_escapes(PcaPathConf *ppc, int literal){  if(ppc)    ppc->escaped = !literal;}/*....................................................................... * Call this function if you know where the index at which the * filename prefix starts in the input line. Otherwise by default, * or if you specify start_index to be -1, the filename is taken * to start after the first unescaped space preceding the cursor, * or the start of the line, which ever comes first. * * Input: *  ppc    PcaPathConf *  The pca_path_completions() configuration object *                        to be configured. *  start_index    int    The index of the start of the filename in *                        the input line, or -1 to select the default. */void ppc_file_start(PcaPathConf *ppc, int start_index){  if(ppc)    ppc->file_start = start_index;}/*....................................................................... * Expand any ~user expression found at the start of a path, leaving * either an empty string in pc->path if there is no ~user expression, * or the corresponding home directory. * * Input: *  pc     PathCache *  The filename cache. *  path  const char *  The path to expand. *  pathlen      int    The max number of characters to look at in path[]. *  literal      int    If true, treat backslashes as literal characters *                      instead of escapes. * Input/Output: *  endp  const char *  A pointer to the next unprocessed character in *                      path[] will be assigned to *endp. * Output: *  return       int    0 - OK *                      1 - Error (a description will have been placed *                                 in pc->errmsg[]). */static int pca_expand_tilde(PathCache *pc, const char *path, int pathlen,			    int literal, const char **endp){  const char *pptr = path;  /* A pointer into path[] */  const char *homedir=NULL; /* A home directory *//* * Clear the pathname buffer. */  _pn_clear_path(pc->path);/* * If the first character is a tilde, then perform home-directory * interpolation. */  if(*pptr == '~') {/* * Skip the tilde character and attempt to read the username that follows * it, into pc->usrnam[]. */    if(pca_read_username(pc, ++pptr, pathlen-1, literal, &pptr))      return 1;/* * Attempt to lookup the home directory of the user. */    homedir = _hd_lookup_home_dir(pc->home, pc->usrnam);    if(!homedir) {      strncpy(pc->errmsg, _hd_last_home_dir_error(pc->home), ERRLEN);      pc->errmsg[ERRLEN] = '\0';      return 1;    };/* * Append the home directory to the pathname string. */    if(_pn_append_to_path(pc->path, homedir, -1, 0) == NULL) {      strcpy(pc->errmsg, "Insufficient memory for home directory expansion");      return 1;    };  };/* * ~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 should * skip over it so that it doesn't get copied into the output pathname */  if(homedir && strcmp(homedir, FS_ROOT_DIR) == 0 &&     (pptr-path) + FS_DIR_SEP_LEN < pathlen &&     strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) {    pptr += FS_DIR_SEP_LEN;  };/* * Return a pointer to the next unprocessed character. */  *endp = pptr;  return 0;}/*....................................................................... * Clear the filename status codes that are recorded before each filename * in the cache. * * Input: *  pc     PathCache *  The filename cache. */static void pca_remove_marks(PathCache *pc){  PathNode *node;         /* A node in the list of directories in the path */  int i;/* * Traverse the absolute directories of the path, clearing the * filename status marks that precede each filename. */  for(node=pc->head; node; node=node->next) {    if(!node->relative) {      for(i=0; i<node->nfile; i++)	*node->files[i] = PCA_F_ENIGMA;    };  };  return;}

⌨️ 快捷键说明

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