📄 filmatch.c
字号:
if (!fexc) break; inverted = TRUE; p = exc + 1; } else { if (!falt) break; p = alt + 1; } } while (*p); *exc = fexc; return( rc );}/* * The functions below enhance the wildcards to match directory names and * to recurse into subdirectories. I've used djgpp's "..." method for * subdirectory traversal. However, unlike djgpp, "..." (or a directory name) * by itself will find all files (it's actually a side-effect of my_findfirst). * * Eg: . -> all files in the current directory * t*\* -> all files in each subdirectory starting with 't' * ... -> all files in the current directory and all subdirectories * *\... -> all files in all subdirectories, but none in the current * * The names are sorted within their directories, according to the current * directory list order (ie. by name or extension). */static FileList *list, *last;static char pathbuf[PATH_MAX+2];static int find_files2( char *, char * );/* * Name: merge_sort * Purpose: sort a list of files * Author: Jason Hood * Date: August 10, 2005 * Passed: list: list of files to be sorted * cnt: number of files * Returns: pointer to new head of list * Notes: use the current directory list sort order. */static FileList *merge_sort( FileList *list, int cnt ){FileList *half;static FileList *p, h; /* none of these are */static int i; /* needed for recursion */ if (cnt <= 1) return( list ); if (cnt == 2) { half = list->next; if (dir_cmp( list->name, half->name ) > 0) { list->next = NULL; half->next = list; last = list; return( half ); } last = half; return( list ); } i = cnt >> 1; p = list; while (--i > 0) p = p->next; half = p->next; p->next = NULL; list = merge_sort( list, cnt >> 1 ); half = merge_sort( half, (cnt >> 1) + (cnt & 1) ); p = &h; for (;;) { if (dir_cmp( list->name, half->name ) <= 0) { p = p->next = list; list = list->next; if (list == NULL) { p->next = half; break; } } else { p = p->next = half; half = half->next; if (half == NULL) { p->next = list; break; } } } last = p; return( h.next );}/* * Name: add_files * Purpose: find and add files to the list * Author: Jason Hood * Date: August 7, 2005 * Passed: name: pointer to the name component of the path * Returns: OK if all added, ERROR if out of memory * Notes: if the path is a subdirectory add all files in it. * sort the entries based on the current directory list sort mode. */static int add_files( char *name ){FTYPE *ft;FFIND ff;FileList *f;FileList *h;int len1, len2;int rc = OK;int cnt = 0; len1 = (int)(name - pathbuf); if (file_exists( pathbuf ) == SUBDIRECTORY && *name) { len1 += strlen( name ) + 1; pathbuf[len1-1] = '/'; pathbuf[len1] = '\0'; } h = list; ft = my_findfirst( pathbuf, &ff, NO_DIRS ); while (ft != NULL) { len2 = strlen( ft->fname ); f = my_malloc( sizeof(*f) + len1 + len2, &rc ); if (f != NULL) { f->next = NULL; memcpy( f->name, pathbuf, len1 ); memcpy( f->name + len1, ft->fname, len2 + 1 ); list = list->next = f; ++cnt; } ft = my_findnext( &ff ); } if (cnt > 1) { h->next = merge_sort( h->next, cnt ); do { list = last; last = last->next; } while (last != NULL); } return( rc );}/* * Name: add_dirs * Purpose: create a list of directories * Author: Jason Hood * Date: August 10, 2005 * Passed: dirs: how to match directories * Returns: pointer to list or NULL if none * Notes: pathbuf contains the pattern. * the list is the directory name only, not the path. */static FileList *add_dirs( int dirs ){FTYPE *ft;FFIND ff;int len, cnt;FileList head, *list, *f;char *p; head.next = NULL; list = &head; cnt = 0; ft = my_findfirst( pathbuf, &ff, dirs ); /* * assume ".." will always be found first ("." is already ignored). */ if (ft != NULL && strcmp( ft->fname, "../" ) == 0) ft = my_findnext( &ff ); while (ft != NULL) { len = strlen( ft->fname ); if (ft->fname[len-1] == '/') { f = my_malloc( sizeof(*f) + len, &len ); if (f != NULL) { f->next = NULL; memcpy( f->name, ft->fname, len + 1 ); list = list->next = f; ++cnt; } } ft = my_findnext( &ff ); } /* * determine if "." or ".." were given explicitly. */ for (p = ff.pattern;; ++p) { if (*p == '.') { len = 1; if (*++p == '.') { len = 2; ++p; } if (*p == '\0' || *p == '!' || *p == ';'#if defined( __UNIX__ ) || *p == ':'#endif ) { f = my_malloc( sizeof(*f) + len + 1, &len ); if (f != NULL) { f->next = NULL; memset( f->name, '.', len ); f->name[len] = '/'; f->name[len+1] = '\0'; list = list->next = f; ++cnt; } } } while (*p && *p != '!' && *p != ';'#if defined( __UNIX__ ) && *p != ':'#endif ) { if (*p == '[') { do { if (*++p == '\\') p += 2; } while (*p != ']'); } ++p; } if (*p == '\0' || *p == '!') break; } return( merge_sort( head.next, cnt ) );}/* * Name: find_dirs * Purpose: traverse subdirectories * Author: Jason Hood * Date: August 7, 2005 * Passed: rest: remaining portion of the pattern * name: where to place directory name * Returns: OK if all added, ERROR if out of memory * Notes: find files in the current directory first, then recurse into * each subdirectory. */static int find_dirs( char *rest, char *name ){FileList *f;int len;int rc = OK; rc = find_files2( rest, name ); *name = '\0'; for (f = add_dirs( ALL_DIRS ); f != NULL && rc == OK; f = next_file( f )) { len = strlen( f->name ); memcpy( name, f->name, len ); rc = find_dirs( rest, name + len ); } return( rc );}/* * Name: find_files2 * Purpose: find files across directories * Author: Jason Hood * Date: August 7, 2005 * Passed: rest: pattern * name: pointer into buffer for path * Returns: OK if all files added, ERROR if out of memory or Ctrl-Break pressed * Notes: a path of "..." can be used to traverse subdirectories. * recurses when given a directory wildcard. */static int find_files2( char *rest, char *name ){FileList *f;int len;char *start = name;int rc = OK; if (g_status.control_break) return( ERROR ); while (*rest) { *name = *rest++; if (*name == '/') { if (name - start == 3 && memcmp( start, "...", 3 ) == 0) return( find_dirs( rest, start ) ); *name = '\0'; if (is_pattern( start )) { for (f = add_dirs( MATCH_DIRS ); f != NULL && rc == OK; f = next_file( f )) { len = strlen( f->name ); memcpy( start, f->name, len ); rc = find_files2( rest, start + len ); } return( rc ); } *name = '/'; start = name + 1; } ++name; } *name = '\0'; rc = add_files( start ); return( rc );}/* * Name: find_files * Purpose: search for files across directories * Author: Jason Hood * Date: August 3, 2005 * Passed: pat: pattern being searched * Returns: pointer to head of filename list or NULL if none found * Notes: directories themselves can contain wildcards and "..." can be used * to traverse subdirectories (eg: "...\*.c" finds all C files in * the current directory and all subdirectories). */FileList *find_files( char *pat ){FileList head;char *p;char *name;char *pattern;int rc; if (*pat == '\0' || !is_valid_pattern( pat, &rc )) return( NULL ); rc = strlen( pat ) + 3; /* two more for "\*" after "..." */ pattern = my_malloc( rc, &rc ); if (rc == ERROR) return( NULL ); strcpy( pattern, pat );#if !defined( __UNIX__ ) /* * now we know the pattern is valid, replace '\' directory separators * with '/', leaving '\' escapes intact. */ for (p = pattern; *p; ++p) { if (*p == '[') { do { if (*++p == '\\') p += 2; } while (*p != ']'); } else if (*p == '\\') *p = '/'; } /* * skip over the drive specifier */ if (pattern[1] == ':') { pathbuf[0] = pattern[0]; pathbuf[1] = ':'; name = pathbuf + 2; p = pattern + 2; } else#endif { name = pathbuf; p = pattern; } /* * explicitly treat "..." as "...\*" to simplify things. */ rc = strlen( p ) - 3; if (rc >= 0 && strcmp( p + rc, "..." ) == 0 && (rc == 0 || p[rc-1] == '/')) strcpy( p + rc + 3, "/*" );#if defined( __UNIX__ ) sort.order_array = sort_order.match;#else sort.order_array = sort_order.ignore;#endif head.next = NULL; list = &head; find_files2( p, name ); my_free( pattern ); return( head.next );}/* * Name: next_file * Purpose: select the next file found by find_files * Author: Jason Hood * Date: August 3, 2005 * Passed: list: current file * Returns: next file, or NULL if finished * Notes: free the memory used by the current file. */FileList *next_file( FileList *list ){FileList *next; next = list->next; my_free( list ); return( next );}/* * Name: is_glob * Purpose: determine if a name is a glob pattern * Author: Jason Hood * Date: August 9, 2005 * Passed: name: name to test * Returns: TRUE if pattern, FALSE if not * Notes: like is_pattern, but also tests for directories. */int is_glob( char *name ){int rc = FALSE;char *p; if (is_pattern( name ) || file_exists( name ) == SUBDIRECTORY) rc = TRUE; else if ((p = strstr( name, "..." )) != NULL) { if ((p == name || p[-1] == '/'#if !defined( __UNIX__ ) || p[-1] == '\\' || p[-1] == ':'#endif ) && (p[3] == '\0' || p[3] == '/'#if !defined( __UNIX__ ) || p[3] == '\\'#endif )) rc = TRUE; } return( rc );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -