From 4694e31659e351cca6626b70936e52068f981b53 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 10 Jun 1993 01:43:06 +0000 Subject: Formerly ar.c.~4~ --- ar.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 2 deletions(-) (limited to 'ar.c') diff --git a/ar.c b/ar.c index 3d6e075..726ceb9 100644 --- a/ar.c +++ b/ar.c @@ -17,10 +17,13 @@ along with GNU Make; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "make.h" -#include "file.h" #ifndef NO_ARCHIVES +#include "file.h" +#include "dep.h" +#include + /* Defined in arscan.c. */ extern long int ar_scan (); extern int ar_member_touch (); @@ -174,5 +177,99 @@ ar_touch (name) return val; } + +/* State of an `ar_glob' run, passed to `ar_glob_match'. */ + +struct ar_glob_state + { + char *arname; + char *pattern; + unsigned int size; + struct nameseq *chain; + unsigned int n; + }; + +/* This function is called by `ar_scan' to match one archive + element against the pattern in STATE. */ + +static long int +ar_glob_match (desc, mem, truncated, + hdrpos, datapos, size, date, uid, gid, mode, + state) + int desc; + char *mem; + int truncated; + long int hdrpos, datapos, size, date; + int uid, gid, mode; + struct ar_glob_state *state; +{ + if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0) + { + /* We have a match. Add it to the chain. */ + struct nameseq *new = (struct nameseq *) xmalloc (state->size); + new->name = concat (state->arname, mem, ")"); + new->next = state->chain; + state->chain = new; + ++state->n; + } + + return 0L; +} + +/* Alphabetic sorting function for `qsort'. */ + +static int +ar_glob_alphacompare (a, b) + char **a, **b; +{ + return strcmp (*a, *b); +} + + +/* Glob for MEMBER_PATTERN in archive ARNAME. + Return a malloc'd chain of matching elements (or nil if none). */ + +struct nameseq * +ar_glob (arname, member_pattern, size) + char *arname, *member_pattern; + unsigned int size; +{ + struct ar_glob_state state; + char **names; + struct nameseq *n; + unsigned int i; + + /* Scan the archive for matches. + ar_glob_match will accumulate them in STATE.chain. */ + i = strlen (arname); + state.arname = (char *) alloca (i + 2); + bcopy (arname, state.arname, i); + state.arname[i] = '('; + state.arname[i + 1] = '\0'; + state.pattern = member_pattern; + state.size = size; + state.chain = 0; + state.n = 0; + (void) ar_scan (arname, ar_glob_match, (long int) &state); + + if (state.chain == 0) + return 0; + + /* Now put the names into a vector for sorting. */ + names = (char **) alloca (state.n * sizeof (char *)); + i = 0; + for (n = state.chain; n != 0; n = n->next) + names[i++] = n->name; + + /* Sort them alphabetically. */ + qsort ((char *) names, i, sizeof (*names), ar_glob_alphacompare); + + /* Put them back into the chain in the sorted order. */ + i = 0; + for (n = state.chain; n != 0; n = n->next) + n->name = names[i++]; + + return state.chain; +} -#endif +#endif /* Not NO_ARCHIVES. */ -- cgit v1.2.3