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

📄 pcache.c

📁 xorp源码hg
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 2000, 2001 by Martin C. Shepherd. *  * All rights reserved. *  * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Software, and to permit persons * to whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *  * Except as contained in this notice, the name of a copyright holder * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * of the copyright holder. */#include <stdlib.h>#include <string.h>#include <stdio.h>#include "libtecla.h"#include "pathutil.h"#include "homedir.h"#include "freelist.h"#include "direader.h"#include "stringrp.h"/* * The new_PcaPathConf() constructor sets the integer first member of * the returned object to the following magic number. This is then * checked for by pca_path_completions() as a sanity check. */#define PPC_ID_CODE 4567/* * A pointer to a structure of the following type can be passed to * the builtin path-completion callback function to modify its behavior. */struct PcaPathConf {  int id;          /* This is set to PPC_ID_CODE by new_PcaPathConf() */  PathCache *pc;   /* The path-list cache in which to look up the executables */  int escaped;     /* If non-zero, backslashes in the input line are */                   /*  interpreted as escaping special characters and */                   /*  spaces, and any special characters and spaces in */                   /*  the listed completions will also be escaped with */                   /*  added backslashes. This is the default behaviour. */                   /* If zero, backslashes are interpreted as being */                   /*  literal parts of the file name, and none are added */                   /*  to the completion suffixes. */  int file_start;  /* The index in the input line of the first character */                   /*  of the file name. If you specify -1 here, */                   /*  pca_path_completions() identifies the */                   /*  the start of the file by looking backwards for */                   /*  an unescaped space, or the beginning of the line. */};/* * Prepended to each chached filename is a character which contains * one of the following status codes. When a given filename (minus * this byte) is passed to the application's check_fn(), the result * is recorded in this byte, such that the next time it is looked * up, we don't have to call check_fn() again. These codes are cleared * whenever the path is scanned and whenever the check_fn() callback * is changed. */typedef enum {  PCA_F_ENIGMA='?', /* The file remains to be checked */  PCA_F_WANTED='+', /* The file has been selected by the caller's callback */  PCA_F_IGNORE='-'  /* The file has been rejected by the caller's callback */} PcaFileStatus;/* * Encapsulate the memory management objects which supply memoy for * the arrays of filenames. */typedef struct {  StringGroup *sg;       /* The memory used to record the names of files */  size_t files_dim;      /* The allocated size of files[] */  char **files;          /* Memory for 'files_dim' pointers to files */  size_t nfiles;         /* The number of filenames currently in files[] */} CacheMem;static CacheMem *new_CacheMem(void);static CacheMem *del_CacheMem(CacheMem *cm);static void rst_CacheMem(CacheMem *cm);/* * Lists of nodes of the following type are used to record the * names and contents of individual directories. */typedef struct PathNode PathNode;struct PathNode {  PathNode *next;   /* The next directory in the path */  int relative;     /* True if the directory is a relative pathname */  CacheMem *mem;    /* The memory used to store dir[] and files[] */  char *dir;        /* The directory pathname (stored in pc->sg) */  int nfile;        /* The number of filenames stored in 'files' */  char **files;     /* Files of interest in the current directory, */                    /*  or NULL if dir[] is a relative pathname */                    /*  who's contents can't be cached. This array */                    /*  and its contents are taken from pc->abs_mem */                    /*  or pc->rel_mem */};/* * Append a new node to the list of directories in the path. */static int add_PathNode(PathCache *pc, const char *dirname);/* * Set the max length of the error-reporting string. There is no point * in this being longer than the width of a typical terminal window. * In composing error messages, I have assumed that this number is * at least 80, so you don't decrease it below this number. */#define ERRLEN 200/* * Set the maximum length allowed for usernames. * names. */#define USR_LEN 100/* * PathCache objects encapsulate the resources needed to record * files of interest from comma-separated lists of directories. */struct PathCache {  FreeList *node_mem;    /* A free-list of PathNode objects */  CacheMem *abs_mem;     /* Memory for the filenames of absolute paths */  CacheMem *rel_mem;     /* Memory for the filenames of relative paths */  PathNode *head;        /* The head of the list of directories in the */                         /*  path, or NULL if no path has been scanned yet. */  PathNode *tail;        /* The tail of the list of directories in the */                         /*  path, or NULL if no path has been scanned yet. */  PathName *path;        /* The fully qualified name of a file */  HomeDir *home;         /* Home-directory lookup object */  DirReader *dr;         /* A portable directory reader */  CplFileConf *cfc;      /* Configuration parameters to pass to */                         /*  cpl_file_completions() */  CplCheckFn *check_fn;  /* The callback used to determine if a given */                         /*  filename should be recorded in the cache. */  void *data;            /* Annonymous data to be passed to pc->check_fn() */  char usrnam[USR_LEN+1];/* The buffer used when reading the names of */                         /*  users. */  char errmsg[ERRLEN+1]; /* Error-report buffer */};/* * Empty the cache. */static void pca_clear_cache(PathCache *pc);/* * Read a username from string[] and record it in pc->usrnam[]. */static int pca_read_username(PathCache *pc, const char *string, int slen,			     int literal, const char **nextp);/* * Extract the next component of a colon separated list of directory * paths. */static int pca_extract_dir(PathCache *pc, const char *path,			   const char **nextp);/* * Scan absolute directories for files of interest, recording their names * in mem->sg and recording pointers to these names in mem->files[]. */static int pca_scan_dir(PathCache *pc, const char *dirname, CacheMem *mem);/* * A qsort() comparison function for comparing the cached filename * strings pointed to by two (char **) array elements. Note that * this ignores the initial cache-status byte of each filename. */static int pca_cmp_matches(const void *v1, const void *v2);/* * A qsort() comparison function for comparing a filename * against an element of an array of pointers to filename cache * entries. */static int pca_cmp_file(const void *v1, const void *v2);/* * Initialize a PcaPathConf configuration objects with the default * options. */static int pca_init_PcaPathConf(PcaPathConf *ppc, PathCache *pc);/* * Make a copy of a completion suffix, suitable for passing to * cpl_add_completion(). */static int pca_prepare_suffix(PathCache *pc, const char *suffix,			      int add_escapes);/* * Return non-zero if the specified string appears to start with a pathname. */static int cpa_cmd_contains_path(const char *prefix, int prefix_len);/* * Return a given prefix with escapes optionally removed. */static const char *pca_prepare_prefix(PathCache *pc, const char *prefix,				      size_t prefix_len, int escaped);/* * If there is a tilde expression at the beginning of the specified path, * place the corresponding home directory into pc->path. Otherwise * just clear pc->path. */static int pca_expand_tilde(PathCache *pc, const char *path, int pathlen,			    int literal, const char **endp);/* * Clear the filename status codes that are recorded before each filename * in the cache. */static void pca_remove_marks(PathCache *pc);/* * Specify how many PathNode's to allocate at a time. */#define PATH_NODE_BLK 30/* * Specify the amount by which the files[] arrays are to be extended * whenever they are found to be too small. */#define FILES_BLK_FACT 256/*....................................................................... * Create a new object who's function is to maintain a cache of * filenames found within a list of directories, and provide quick * lookup and completion of selected files in this cache. * * Output: *  return     PathCache *  The new, initially empty cache, or NULL *                          on error. */PathCache *new_PathCache(void){  PathCache *pc;  /* The object to be returned *//* * Allocate the container. */  pc = (PathCache *)malloc(sizeof(PathCache));  if(!pc) {    fprintf(stderr, "new_PathCache: Insufficient memory.\n");    return NULL;  };/* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to del_PathCache(). */  pc->node_mem = NULL;  pc->abs_mem = NULL;  pc->rel_mem = NULL;  pc->head = NULL;  pc->tail = NULL;  pc->path = NULL;  pc->home = NULL;  pc->dr = NULL;  pc->cfc = NULL;  pc->check_fn = 0;  pc->data = NULL;  pc->usrnam[0] = '\0';  pc->errmsg[0] = '\0';/* * Allocate the freelist of directory list nodes. */  pc->node_mem = _new_FreeList("new_PathCache", sizeof(PathNode),			       PATH_NODE_BLK);  if(!pc->node_mem)    return del_PathCache(pc);/* * Allocate memory for recording names of files in absolute paths. */  pc->abs_mem = new_CacheMem();  if(!pc->abs_mem)    return del_PathCache(pc);/* * Allocate memory for recording names of files in relative paths. */  pc->rel_mem = new_CacheMem();  if(!pc->rel_mem)    return del_PathCache(pc);/* * Allocate a pathname buffer. */  pc->path = _new_PathName();  if(!pc->path)    return del_PathCache(pc);/* * Allocate an object for looking up home-directories. */  pc->home = _new_HomeDir();  if(!pc->home)    return del_PathCache(pc);/* * Allocate an object for reading directories. */  pc->dr = _new_DirReader();  if(!pc->dr)    return del_PathCache(pc);/* * Allocate a cpl_file_completions() configuration object. */  pc->cfc = new_CplFileConf();  if(!pc->cfc)    return del_PathCache(pc);/* * Configure cpl_file_completions() to use check_fn() to select * files of interest. */  cfc_set_check_fn(pc->cfc, pc->check_fn, pc->data);/* * Return the cache, ready for use. */  return pc;}/*....................................................................... * Delete a given cache of files, returning the resources that it * was using to the system. * * Input: *  pc      PathCache *  The cache to be deleted (can be NULL). * Output: *  return  PathCache *  The deleted object (ie. allways NULL). */PathCache *del_PathCache(PathCache *pc){  if(pc) {/* * Delete the memory of the list of path nodes. */    pc->node_mem = _del_FreeList(NULL, pc->node_mem, 1);/* * Delete the memory used to record filenames. */    pc->abs_mem = del_CacheMem(pc->abs_mem);    pc->rel_mem = del_CacheMem(pc->rel_mem);/* * The list of PathNode's was already deleted when node_mem was * deleted. */    pc->head = NULL;    pc->tail = NULL;/* * Delete the pathname buffer. */    pc->path = _del_PathName(pc->path);/* * Delete the home-directory lookup object. */    pc->home = _del_HomeDir(pc->home);/* * Delete the directory reader. */    pc->dr = _del_DirReader(pc->dr);/* * Delete the cpl_file_completions() config object. */    pc->cfc = del_CplFileConf(pc->cfc);/* * Delete the container. */    free(pc);  };  return NULL;}/*....................................................................... * If you want subsequent calls to pca_lookup_file() and * pca_path_completions() to only return the filenames of certain * types of files, for example executables, or filenames ending in * ".ps", call this function to register a file-selection callback * function. This callback function takes the full pathname of a file, * plus application-specific data, and returns 1 if the file is of * interest, and zero otherwise. * * Input: *  pc         PathCache *  The filename cache. *  check_fn  CplCheckFn *  The function to call to see if the name of *                          a given file should be included in the *                          cache. This determines what type of files *                          will reside in the cache. To revert to *                          selecting all files, regardless of type, *                          pass 0 here. *  data            void *  You can pass a pointer to anything you *                          like here, including NULL. It will be *                          passed to your check_fn() callback *                          function, for its private use. */void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, void *data){  if(pc) {/* * If the callback or its data pointer have changed, clear the cached * statuses of files that were accepted or rejected by the previous * calback. */

⌨️ 快捷键说明

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