VirtualBox

source: kBuild/trunk/src/gmakenew/ar.c@ 902

Last change on this file since 902 was 503, checked in by bird, 18 years ago

Untested merge with GNU Make v3.81 (vendor/gnumake/2005-05-16 -> vendor/gnumake/current).

  • Property svn:eol-style set to native
File size: 7.8 KB
Line 
1/* Interface to `ar' archives for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
31998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
4Foundation, Inc.
5This file is part of GNU Make.
6
7GNU Make is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
10
11GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16GNU Make; see the file COPYING. If not, write to the Free Software
17Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
18
19#include "make.h"
20
21#ifndef NO_ARCHIVES
22
23#include "filedef.h"
24#include "dep.h"
25#include <fnmatch.h>
26
27/* Defined in arscan.c. */
28extern long int ar_scan PARAMS ((char *archive, long int (*function) (), long int arg));
29extern int ar_name_equal PARAMS ((char *name, char *mem, int truncated));
30#ifndef VMS
31extern int ar_member_touch PARAMS ((char *arname, char *memname));
32#endif
33
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. */
38
39int
40ar_name (char *name)
41{
42 char *p = strchr (name, '(');
43 char *end;
44
45 if (p == 0 || p == name)
46 return 0;
47
48 end = p + strlen (p) - 1;
49 if (*end != ')')
50 return 0;
51
52 if (p[1] == '(' && end[-1] == ')')
53 fatal (NILF, _("attempt to use unsupported feature: `%s'"), name);
54
55 return 1;
56}
57
58
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. */
62
63void
64ar_parse_name (char *name, char **arname_p, char **memname_p)
65{
66 char *p = strchr (name, '('), *end = name + strlen (name) - 1;
67
68 if (arname_p != 0)
69 *arname_p = savestring (name, p - name);
70
71 if (memname_p != 0)
72 *memname_p = savestring (p + 1, end - (p + 1));
73}
74
75
76static long int ar_member_date_1 PARAMS ((int desc, char *mem, int truncated, long int hdrpos,
77 long int datapos, long int size, long int date, int uid, int gid, int mode, char *name));
78
79/* Return the modtime of NAME. */
80
81time_t
82ar_member_date (char *name)
83{
84 char *arname;
85 int arname_used = 0;
86 char *memname;
87 long int val;
88
89 ar_parse_name (name, &arname, &memname);
90
91 /* Make sure we know the modtime of the archive itself because we are
92 likely to be called just before commands to remake a member are run,
93 and they will change the archive itself.
94
95 But we must be careful not to enter_file the archive itself if it does
96 not exist, because pattern_search assumes that files found in the data
97 base exist or can be made. */
98 {
99 struct file *arfile;
100 arfile = lookup_file (arname);
101 if (arfile == 0 && file_exists_p (arname))
102 {
103 arfile = enter_file (arname);
104 arname_used = 1;
105 }
106
107 if (arfile != 0)
108 (void) f_mtime (arfile, 0);
109 }
110
111 val = ar_scan (arname, ar_member_date_1, (long int) memname);
112
113 if (!arname_used)
114 free (arname);
115 free (memname);
116
117 return (val <= 0 ? (time_t) -1 : (time_t) val);
118}
119
120/* This function is called by `ar_scan' to find which member to look at. */
121
122/* ARGSUSED */
123static long int
124ar_member_date_1 (int desc UNUSED, char *mem, int truncated,
125 long int hdrpos UNUSED, long int datapos UNUSED,
126 long int size UNUSED, long int date,
127 int uid UNUSED, int gid UNUSED, int mode UNUSED, char *name)
128{
129 return ar_name_equal (name, mem, truncated) ? date : 0;
130}
131
132
133/* Set the archive-member NAME's modtime to now. */
134
135#ifdef VMS
136int
137ar_touch (char *name)
138{
139 error (NILF, _("touch archive member is not available on VMS"));
140 return -1;
141}
142#else
143int
144ar_touch (char *name)
145{
146 char *arname, *memname;
147 int arname_used = 0;
148 register int val;
149
150 ar_parse_name (name, &arname, &memname);
151
152 /* Make sure we know the modtime of the archive itself before we
153 touch the member, since this will change the archive itself. */
154 {
155 struct file *arfile;
156 arfile = lookup_file (arname);
157 if (arfile == 0)
158 {
159 arfile = enter_file (arname);
160 arname_used = 1;
161 }
162
163 (void) f_mtime (arfile, 0);
164 }
165
166 val = 1;
167 switch (ar_member_touch (arname, memname))
168 {
169 case -1:
170 error (NILF, _("touch: Archive `%s' does not exist"), arname);
171 break;
172 case -2:
173 error (NILF, _("touch: `%s' is not a valid archive"), arname);
174 break;
175 case -3:
176 perror_with_name ("touch: ", arname);
177 break;
178 case 1:
179 error (NILF,
180 _("touch: Member `%s' does not exist in `%s'"), memname, arname);
181 break;
182 case 0:
183 val = 0;
184 break;
185 default:
186 error (NILF,
187 _("touch: Bad return code from ar_member_touch on `%s'"), name);
188 }
189
190 if (!arname_used)
191 free (arname);
192 free (memname);
193
194 return val;
195}
196#endif /* !VMS */
197
198
199/* State of an `ar_glob' run, passed to `ar_glob_match'. */
200
201struct ar_glob_state
202 {
203 char *arname;
204 char *pattern;
205 unsigned int size;
206 struct nameseq *chain;
207 unsigned int n;
208 };
209
210/* This function is called by `ar_scan' to match one archive
211 element against the pattern in STATE. */
212
213static long int
214ar_glob_match (int desc UNUSED, char *mem, int truncated UNUSED,
215 long int hdrpos UNUSED, long int datapos UNUSED,
216 long int size UNUSED, long int date UNUSED, int uid UNUSED,
217 int gid UNUSED, int mode UNUSED, struct ar_glob_state *state)
218{
219 if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
220 {
221 /* We have a match. Add it to the chain. */
222 struct nameseq *new = (struct nameseq *) xmalloc (state->size);
223 new->name = concat (state->arname, mem, ")");
224 new->next = state->chain;
225 state->chain = new;
226 ++state->n;
227 }
228
229 return 0L;
230}
231
232/* Return nonzero if PATTERN contains any metacharacters.
233 Metacharacters can be quoted with backslashes if QUOTE is nonzero. */
234static int
235glob_pattern_p (const char *pattern, int quote)
236{
237 const char *p;
238 int open = 0;
239
240 for (p = pattern; *p != '\0'; ++p)
241 switch (*p)
242 {
243 case '?':
244 case '*':
245 return 1;
246
247 case '\\':
248 if (quote)
249 ++p;
250 break;
251
252 case '[':
253 open = 1;
254 break;
255
256 case ']':
257 if (open)
258 return 1;
259 break;
260 }
261
262 return 0;
263}
264
265/* Glob for MEMBER_PATTERN in archive ARNAME.
266 Return a malloc'd chain of matching elements (or nil if none). */
267
268struct nameseq *
269ar_glob (char *arname, char *member_pattern, unsigned int size)
270{
271 struct ar_glob_state state;
272 char **names;
273 struct nameseq *n;
274 unsigned int i;
275
276 if (! glob_pattern_p (member_pattern, 1))
277 return 0;
278
279 /* Scan the archive for matches.
280 ar_glob_match will accumulate them in STATE.chain. */
281 i = strlen (arname);
282 state.arname = (char *) alloca (i + 2);
283 bcopy (arname, state.arname, i);
284 state.arname[i] = '(';
285 state.arname[i + 1] = '\0';
286 state.pattern = member_pattern;
287 state.size = size;
288 state.chain = 0;
289 state.n = 0;
290 (void) ar_scan (arname, ar_glob_match, (long int) &state);
291
292 if (state.chain == 0)
293 return 0;
294
295 /* Now put the names into a vector for sorting. */
296 names = (char **) alloca (state.n * sizeof (char *));
297 i = 0;
298 for (n = state.chain; n != 0; n = n->next)
299 names[i++] = n->name;
300
301 /* Sort them alphabetically. */
302 qsort ((char *) names, i, sizeof (*names), alpha_compare);
303
304 /* Put them back into the chain in the sorted order. */
305 i = 0;
306 for (n = state.chain; n != 0; n = n->next)
307 n->name = names[i++];
308
309 return state.chain;
310}
311
312#endif /* Not NO_ARCHIVES. */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette