summaryrefslogtreecommitdiff
path: root/ar.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>1993-06-10 01:43:06 +0000
committerRoland McGrath <roland@redhat.com>1993-06-10 01:43:06 +0000
commit4694e31659e351cca6626b70936e52068f981b53 (patch)
treedfc779ce563b937a71aca52e22ec84a9bf766d88 /ar.c
parent3d6b586776395863b24bee0a925873f37e9b4b4c (diff)
downloadgunmake-4694e31659e351cca6626b70936e52068f981b53.tar.gz
Formerly ar.c.~4~
Diffstat (limited to 'ar.c')
-rw-r--r--ar.c101
1 files changed, 99 insertions, 2 deletions
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 <fnmatch.h>
+
/* 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. */