openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

complete.c (4489B)


      1 /*  $Revision: 1.4 $
      2 **
      3 **  History and file completion functions for editline library.
      4 */
      5 
      6 #ifdef INCLUDE_EDITLINE
      7 
      8 #include "editline.h"
      9 
     10 #if	defined(NEED_STRDUP)
     11 /*
     12 **  Return an allocated copy of a string.
     13 */
     14 char *
     15 strdup(p)
     16     char	*p;
     17 {
     18     char	*new;
     19 
     20     if ((new = NEW(char, strlen(p) + 1)) != NULL)
     21 	(void)strcpy(new, p);
     22     return new;
     23 }
     24 #endif	/* defined(NEED_STRDUP) */
     25 
     26 #if     defined(USE_POSIX_COMPLETION)
     27 
     28 /*
     29 **  strcmp-like sorting predicate for qsort.
     30 */
     31 STATIC int
     32 compare(p1, p2)
     33     CONST void	*p1;
     34     CONST void	*p2;
     35 {
     36     CONST char	**v1;
     37     CONST char	**v2;
     38 
     39     v1 = (CONST char **)p1;
     40     v2 = (CONST char **)p2;
     41     return strcmp(*v1, *v2);
     42 }
     43 
     44 /*
     45 **  Fill in *avp with an array of names that match file, up to its length.
     46 **  Ignore . and .. .
     47 */
     48 STATIC int
     49 FindMatches(dir, file, avp)
     50     char	*dir;
     51     char	*file;
     52     char	***avp;
     53 {
     54     char	**av;
     55     char	**new;
     56     char	*p;
     57     DIR		*dp;
     58     DIRENTRY	*ep;
     59     SIZE_T	ac;
     60     SIZE_T	len;
     61 
     62     if ((dp = opendir(dir)) == NULL)
     63 	return 0;
     64 
     65     av = NULL;
     66     ac = 0;
     67     len = strlen(file);
     68     while ((ep = readdir(dp)) != NULL) {
     69 	p = ep->d_name;
     70 	if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
     71 	    continue;
     72 	if (len && strncmp(p, file, len) != 0)
     73 	    continue;
     74 
     75 	if ((ac % MEM_INC) == 0) {
     76 	    if ((new = NEW(char*, ac + MEM_INC)) == NULL)
     77 		break;
     78 	    if (ac) {
     79 		COPYFROMTO(new, av, ac * sizeof (char **));
     80 		DISPOSE(av);
     81 	    }
     82 	    *avp = av = new;
     83 	}
     84 
     85 	if ((av[ac] = sal_strdup(p)) == NULL) {
     86 	    if (ac == 0)
     87 		DISPOSE(av);
     88 	    break;
     89 	}
     90 	ac++;
     91     }
     92 
     93     /* Clean up and return. */
     94     (void)closedir(dp);
     95     if (ac)
     96 	qsort(av, ac, sizeof (char **), compare);
     97     return ac;
     98 }
     99 
    100 /*
    101 **  Split a pathname into allocated directory and trailing filename parts.
    102 */
    103 STATIC int
    104 SplitPath(path, dirpart, filepart)
    105     char	*path;
    106     char	**dirpart;
    107     char	**filepart;
    108 {
    109     static char	DOT[] = ".";
    110     char	*dpart;
    111     char	*fpart;
    112 
    113     if ((fpart = strrchr(path, '/')) == NULL) {
    114 	if ((dpart = sal_strdup(DOT)) == NULL)
    115 	    return -1;
    116 	if ((fpart = sal_strdup(path)) == NULL) {
    117 	    DISPOSE(dpart);
    118 	    return -1;
    119 	}
    120     }
    121     else {
    122 	if ((dpart = sal_strdup(path)) == NULL)
    123 	    return -1;
    124 	dpart[fpart - path + 1] = '\0';
    125 	if ((fpart = sal_strdup(++fpart)) == NULL) {
    126 	    DISPOSE(dpart);
    127 	    return -1;
    128 	}
    129     }
    130     *dirpart = dpart;
    131     *filepart = fpart;
    132     return 0;
    133 }
    134 
    135 #endif /* USE_POSIX_COMPLETION */
    136 
    137 /*
    138 **  Attempt to complete the pathname, returning an allocated copy.
    139 **  Fill in *unique if we completed it, or set it to 0 if ambiguous.
    140 */
    141 char *
    142 rl_complete_file(pathname, unique)
    143     char	*pathname;
    144     int		*unique;
    145 {
    146 #if     defined(USE_POSIX_COMPLETION)
    147     char	**av;
    148     char	*dir;
    149     char	*file;
    150     char	*new;
    151     char	*p;
    152     SIZE_T	ac;
    153     SIZE_T	end;
    154     SIZE_T	i;
    155     SIZE_T	j;
    156     SIZE_T	len;
    157 
    158     if (SplitPath(pathname, &dir, &file) < 0)
    159 	return NULL;
    160     if ((ac = FindMatches(dir, file, &av)) == 0) {
    161 	DISPOSE(dir);
    162 	DISPOSE(file);
    163 	return NULL;
    164     }
    165 
    166     p = NULL;
    167     len = strlen(file);
    168     if (ac == 1) {
    169 	/* Exactly one match -- finish it off. */
    170 	*unique = 1;
    171 	j = strlen(av[0]) - len + 2;
    172 	if ((p = NEW(char, j + 1)) != NULL) {
    173 	    COPYFROMTO(p, av[0] + len, j);
    174 	    if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
    175 		(void)strcpy(new, dir);
    176 		(void)strcat(new, "/");
    177 		(void)strcat(new, av[0]);
    178 		rl_add_slash(new, p);
    179 		DISPOSE(new);
    180 	    }
    181 	}
    182     }
    183     else {
    184 	/* Find largest matching substring. */
    185 	for (*unique = 0, i = len, end = strlen(av[0]); i < end; i++)
    186 	    for (j = 1; j < ac; j++)
    187 		if (av[0][i] != av[j][i])
    188 		    goto breakout;
    189 breakout:
    190 	if (i > len) {
    191 	    j = i - len + 1;
    192 	    if ((p = NEW(char, j)) != NULL) {
    193 		COPYFROMTO(p, av[0] + len, j);
    194 		p[j - 1] = '\0';
    195 	    }
    196 	}
    197     }
    198 
    199     /* Clean up and return. */
    200     DISPOSE(dir);
    201     DISPOSE(file);
    202     for (i = 0; i < ac; i++)
    203 	DISPOSE(av[i]);
    204     DISPOSE(av);
    205     return p;
    206 #else
    207     return 0;
    208 #endif /* USE_POSIX_COMPLETION */
    209 }
    210 
    211 /*
    212 **  Return all possible completions.
    213 */
    214 int
    215 rl_list_possib_file(pathname, avp)
    216     char	*pathname;
    217     char	***avp;
    218 {
    219 #if     defined(USE_POSIX_COMPLETION)
    220     char	*dir;
    221     char	*file;
    222     int		ac;
    223 
    224     if (SplitPath(pathname, &dir, &file) < 0)
    225 	return 0;
    226     ac = FindMatches(dir, file, avp);
    227     DISPOSE(dir);
    228     DISPOSE(file);
    229     return ac;
    230 #else
    231     return 0;
    232 #endif /* USE_POSIX_COMPLETION */
    233 }
    234 
    235 #else /* INCLUDE_EDITLINE */
    236 int _editline_complete_not_empty;
    237 #endif /* INCLUDE_EDITLINE */