VirtualBox

source: kBuild/vendor/gnumake/2005-05-16/ar.c@ 1989

Last change on this file since 1989 was 153, checked in by bird, 20 years ago

GNU Make 3.81beta1.

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