VirtualBox

source: kBuild/vendor/gnumake/3.82-cvs/ar.c@ 2580

Last change on this file since 2580 was 2580, checked in by bird, 12 years ago

Importing the make-3-82 CVS tag with --auto-props but no keywords.

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