Release GNU make 3.81.
[make.git] / ar.c
blob4d9f1bb1dd7bd549cd0a2648c4405099893c1595
1 /* Interface to `ar' archives for GNU Make.
2 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
4 Foundation, Inc.
5 This file is part of GNU Make.
7 GNU Make is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 2, or (at your option) any later version.
11 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along with
16 GNU Make; see the file COPYING. If not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
19 #include "make.h"
21 #ifndef NO_ARCHIVES
23 #include "filedef.h"
24 #include "dep.h"
25 #include <fnmatch.h>
27 /* Defined in arscan.c. */
28 extern long int ar_scan PARAMS ((char *archive, long int (*function) (), long int arg));
29 extern int ar_name_equal PARAMS ((char *name, char *mem, int truncated));
30 #ifndef VMS
31 extern int ar_member_touch PARAMS ((char *arname, char *memname));
32 #endif
34 /* Return nonzero if NAME is an archive-member reference, zero if not.
35 An archive-member reference is a name like `lib(member)'.
36 If a name like `lib((entry))' is used, a fatal error is signaled at
37 the attempt to use this unsupported feature. */
39 int
40 ar_name (char *name)
42 char *p = strchr (name, '(');
43 char *end;
45 if (p == 0 || p == name)
46 return 0;
48 end = p + strlen (p) - 1;
49 if (*end != ')')
50 return 0;
52 if (p[1] == '(' && end[-1] == ')')
53 fatal (NILF, _("attempt to use unsupported feature: `%s'"), name);
55 return 1;
59 /* Parse the archive-member reference NAME into the archive and member names.
60 Put the malloc'd archive name in *ARNAME_P if ARNAME_P is non-nil;
61 put the malloc'd member name in *MEMNAME_P if MEMNAME_P is non-nil. */
63 void
64 ar_parse_name (char *name, char **arname_p, char **memname_p)
66 char *p = strchr (name, '('), *end = name + strlen (name) - 1;
68 if (arname_p != 0)
69 *arname_p = savestring (name, p - name);
71 if (memname_p != 0)
72 *memname_p = savestring (p + 1, end - (p + 1));
75 static long int ar_member_date_1 PARAMS ((int desc, char *mem, int truncated, long int hdrpos,
76 long int datapos, long int size, long int date, int uid, int gid, int mode, char *name));
78 /* Return the modtime of NAME. */
80 time_t
81 ar_member_date (char *name)
83 char *arname;
84 int arname_used = 0;
85 char *memname;
86 long int val;
88 ar_parse_name (name, &arname, &memname);
90 /* Make sure we know the modtime of the archive itself because we are
91 likely to be called just before commands to remake a member are run,
92 and they will change the archive itself.
94 But we must be careful not to enter_file the archive itself if it does
95 not exist, because pattern_search assumes that files found in the data
96 base exist or can be made. */
98 struct file *arfile;
99 arfile = lookup_file (arname);
100 if (arfile == 0 && file_exists_p (arname))
102 arfile = enter_file (arname);
103 arname_used = 1;
106 if (arfile != 0)
107 (void) f_mtime (arfile, 0);
110 val = ar_scan (arname, ar_member_date_1, (long int) memname);
112 if (!arname_used)
113 free (arname);
114 free (memname);
116 return (val <= 0 ? (time_t) -1 : (time_t) val);
119 /* This function is called by `ar_scan' to find which member to look at. */
121 /* ARGSUSED */
122 static long int
123 ar_member_date_1 (int desc UNUSED, char *mem, int truncated,
124 long int hdrpos UNUSED, long int datapos UNUSED,
125 long int size UNUSED, long int date,
126 int uid UNUSED, int gid UNUSED, int mode UNUSED, char *name)
128 return ar_name_equal (name, mem, truncated) ? date : 0;
131 /* Set the archive-member NAME's modtime to now. */
133 #ifdef VMS
135 ar_touch (char *name)
137 error (NILF, _("touch archive member is not available on VMS"));
138 return -1;
140 #else
142 ar_touch (char *name)
144 char *arname, *memname;
145 int arname_used = 0;
146 register int val;
148 ar_parse_name (name, &arname, &memname);
150 /* Make sure we know the modtime of the archive itself before we
151 touch the member, since this will change the archive itself. */
153 struct file *arfile;
154 arfile = lookup_file (arname);
155 if (arfile == 0)
157 arfile = enter_file (arname);
158 arname_used = 1;
161 (void) f_mtime (arfile, 0);
164 val = 1;
165 switch (ar_member_touch (arname, memname))
167 case -1:
168 error (NILF, _("touch: Archive `%s' does not exist"), arname);
169 break;
170 case -2:
171 error (NILF, _("touch: `%s' is not a valid archive"), arname);
172 break;
173 case -3:
174 perror_with_name ("touch: ", arname);
175 break;
176 case 1:
177 error (NILF,
178 _("touch: Member `%s' does not exist in `%s'"), memname, arname);
179 break;
180 case 0:
181 val = 0;
182 break;
183 default:
184 error (NILF,
185 _("touch: Bad return code from ar_member_touch on `%s'"), name);
188 if (!arname_used)
189 free (arname);
190 free (memname);
192 return val;
194 #endif /* !VMS */
196 /* State of an `ar_glob' run, passed to `ar_glob_match'. */
198 struct ar_glob_state
200 char *arname;
201 char *pattern;
202 unsigned int size;
203 struct nameseq *chain;
204 unsigned int n;
207 /* This function is called by `ar_scan' to match one archive
208 element against the pattern in STATE. */
210 static long int
211 ar_glob_match (int desc UNUSED, char *mem, int truncated UNUSED,
212 long int hdrpos UNUSED, long int datapos UNUSED,
213 long int size UNUSED, long int date UNUSED, int uid UNUSED,
214 int gid UNUSED, int mode UNUSED, struct ar_glob_state *state)
216 if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
218 /* We have a match. Add it to the chain. */
219 struct nameseq *new = (struct nameseq *) xmalloc (state->size);
220 new->name = concat (state->arname, mem, ")");
221 new->next = state->chain;
222 state->chain = new;
223 ++state->n;
226 return 0L;
229 /* Return nonzero if PATTERN contains any metacharacters.
230 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
231 static int
232 glob_pattern_p (const char *pattern, int quote)
234 const char *p;
235 int open = 0;
237 for (p = pattern; *p != '\0'; ++p)
238 switch (*p)
240 case '?':
241 case '*':
242 return 1;
244 case '\\':
245 if (quote)
246 ++p;
247 break;
249 case '[':
250 open = 1;
251 break;
253 case ']':
254 if (open)
255 return 1;
256 break;
259 return 0;
262 /* Glob for MEMBER_PATTERN in archive ARNAME.
263 Return a malloc'd chain of matching elements (or nil if none). */
265 struct nameseq *
266 ar_glob (char *arname, char *member_pattern, unsigned int size)
268 struct ar_glob_state state;
269 char **names;
270 struct nameseq *n;
271 unsigned int i;
273 if (! glob_pattern_p (member_pattern, 1))
274 return 0;
276 /* Scan the archive for matches.
277 ar_glob_match will accumulate them in STATE.chain. */
278 i = strlen (arname);
279 state.arname = (char *) alloca (i + 2);
280 bcopy (arname, state.arname, i);
281 state.arname[i] = '(';
282 state.arname[i + 1] = '\0';
283 state.pattern = member_pattern;
284 state.size = size;
285 state.chain = 0;
286 state.n = 0;
287 (void) ar_scan (arname, ar_glob_match, (long int) &state);
289 if (state.chain == 0)
290 return 0;
292 /* Now put the names into a vector for sorting. */
293 names = (char **) alloca (state.n * sizeof (char *));
294 i = 0;
295 for (n = state.chain; n != 0; n = n->next)
296 names[i++] = n->name;
298 /* Sort them alphabetically. */
299 qsort ((char *) names, i, sizeof (*names), alpha_compare);
301 /* Put them back into the chain in the sorted order. */
302 i = 0;
303 for (n = state.chain; n != 0; n = n->next)
304 n->name = names[i++];
306 return state.chain;
309 #endif /* Not NO_ARCHIVES. */