Fri Aug 28 18:34:46 2020 UTC ()
make(1): clean up arch.c

Remove redundant parts of the function comments.  Move the "side
effects" to the main section, since these effects are main effects, not
side effects.

Remove the redundant prototype for ArchFree.


(rillig)
diff -r1.101 -r1.102 src/usr.bin/make/arch.c

cvs diff -r1.101 -r1.102 src/usr.bin/make/arch.c (switch to unified diff)

--- src/usr.bin/make/arch.c 2020/08/28 04:48:56 1.101
+++ src/usr.bin/make/arch.c 2020/08/28 18:34:45 1.102
@@ -1,1338 +1,1241 @@ @@ -1,1338 +1,1241 @@
1/* $NetBSD: arch.c,v 1.101 2020/08/28 04:48:56 rillig Exp $ */ 1/* $NetBSD: arch.c,v 1.102 2020/08/28 18:34:45 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1989 by Berkeley Softworks 36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved. 37 * All rights reserved.
38 * 38 *
39 * This code is derived from software contributed to Berkeley by 39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor. 40 * Adam de Boor.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by the University of 52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors. 53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors 54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software 55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission. 56 * without specific prior written permission.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: arch.c,v 1.101 2020/08/28 04:48:56 rillig Exp $"; 72static char rcsid[] = "$NetBSD: arch.c,v 1.102 2020/08/28 18:34:45 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; 77static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
78#else 78#else
79__RCSID("$NetBSD: arch.c,v 1.101 2020/08/28 04:48:56 rillig Exp $"); 79__RCSID("$NetBSD: arch.c,v 1.102 2020/08/28 18:34:45 rillig Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * arch.c -- 85 * arch.c --
86 * Functions to manipulate libraries, archives and their members. 86 * Functions to manipulate libraries, archives and their members.
87 * 87 *
88 * Once again, cacheing/hashing comes into play in the manipulation 88 * Once again, cacheing/hashing comes into play in the manipulation
89 * of archives. The first time an archive is referenced, all of its members' 89 * of archives. The first time an archive is referenced, all of its members'
90 * headers are read and hashed and the archive closed again. All hashed 90 * headers are read and hashed and the archive closed again. All hashed
91 * archives are kept on a list which is searched each time an archive member 91 * archives are kept on a list which is searched each time an archive member
92 * is referenced. 92 * is referenced.
93 * 93 *
94 * The interface to this module is: 94 * The interface to this module is:
95 * Arch_ParseArchive Given an archive specification, return a list 95 * Arch_ParseArchive Given an archive specification, return a list
96 * of GNode's, one for each member in the spec. 96 * of GNode's, one for each member in the spec.
97 * FAILURE is returned if the specification is 97 * FAILURE is returned if the specification is
98 * invalid for some reason. 98 * invalid for some reason.
99 * 99 *
100 * Arch_Touch Alter the modification time of the archive 100 * Arch_Touch Alter the modification time of the archive
101 * member described by the given node to be 101 * member described by the given node to be
102 * the current time. 102 * the current time.
103 * 103 *
104 * Arch_TouchLib Update the modification time of the library 104 * Arch_TouchLib Update the modification time of the library
105 * described by the given node. This is special 105 * described by the given node. This is special
106 * because it also updates the modification time 106 * because it also updates the modification time
107 * of the library's table of contents. 107 * of the library's table of contents.
108 * 108 *
109 * Arch_MTime Find the modification time of a member of 109 * Arch_MTime Find the modification time of a member of
110 * an archive *in the archive*. The time is also 110 * an archive *in the archive*. The time is also
111 * placed in the member's GNode. Returns the 111 * placed in the member's GNode. Returns the
112 * modification time. 112 * modification time.
113 * 113 *
114 * Arch_MemTime Find the modification time of a member of 114 * Arch_MemTime Find the modification time of a member of
115 * an archive. Called when the member doesn't 115 * an archive. Called when the member doesn't
116 * already exist. Looks in the archive for the 116 * already exist. Looks in the archive for the
117 * modification time. Returns the modification 117 * modification time. Returns the modification
118 * time. 118 * time.
119 * 119 *
120 * Arch_FindLib Search for a library along a path. The 120 * Arch_FindLib Search for a library along a path. The
121 * library name in the GNode should be in 121 * library name in the GNode should be in
122 * -l<name> format. 122 * -l<name> format.
123 * 123 *
124 * Arch_LibOODate Special function to decide if a library node 124 * Arch_LibOODate Special function to decide if a library node
125 * is out-of-date. 125 * is out-of-date.
126 * 126 *
127 * Arch_Init Initialize this module. 127 * Arch_Init Initialize this module.
128 * 128 *
129 * Arch_End Cleanup this module. 129 * Arch_End Cleanup this module.
130 */ 130 */
131 131
132#include <sys/types.h> 132#include <sys/types.h>
133#include <sys/stat.h> 133#include <sys/stat.h>
134#include <sys/time.h> 134#include <sys/time.h>
135#include <sys/param.h> 135#include <sys/param.h>
136 136
137#include <ar.h> 137#include <ar.h>
138#include <ctype.h> 138#include <ctype.h>
139#include <stdio.h> 139#include <stdio.h>
140#include <stdlib.h> 140#include <stdlib.h>
141#include <utime.h> 141#include <utime.h>
142 142
143#include "make.h" 143#include "make.h"
144#include "hash.h" 144#include "hash.h"
145#include "dir.h" 145#include "dir.h"
146#include "config.h" 146#include "config.h"
147 147
148#ifdef TARGET_MACHINE 148#ifdef TARGET_MACHINE
149#undef MAKE_MACHINE 149#undef MAKE_MACHINE
150#define MAKE_MACHINE TARGET_MACHINE 150#define MAKE_MACHINE TARGET_MACHINE
151#endif 151#endif
152#ifdef TARGET_MACHINE_ARCH 152#ifdef TARGET_MACHINE_ARCH
153#undef MAKE_MACHINE_ARCH 153#undef MAKE_MACHINE_ARCH
154#define MAKE_MACHINE_ARCH TARGET_MACHINE_ARCH 154#define MAKE_MACHINE_ARCH TARGET_MACHINE_ARCH
155#endif 155#endif
156 156
157static Lst archives; /* Lst of archives we've already examined */ 157static Lst archives; /* Lst of archives we've already examined */
158 158
159typedef struct Arch { 159typedef struct Arch {
160 char *name; /* Name of archive */ 160 char *name; /* Name of archive */
161 Hash_Table members; /* All the members of the archive described 161 Hash_Table members; /* All the members of the archive described
162 * by <name, struct ar_hdr *> key/value pairs */ 162 * by <name, struct ar_hdr *> key/value pairs */
163 char *fnametab; /* Extended name table strings */ 163 char *fnametab; /* Extended name table strings */
164 size_t fnamesize; /* Size of the string table */ 164 size_t fnamesize; /* Size of the string table */
165} Arch; 165} Arch;
166 166
167static int ArchFindArchive(const void *, const void *); 167static int ArchFindArchive(const void *, const void *);
168#ifdef CLEANUP 
169static void ArchFree(void *); 
170#endif 
171static struct ar_hdr *ArchStatMember(const char *, const char *, Boolean); 168static struct ar_hdr *ArchStatMember(const char *, const char *, Boolean);
172static FILE *ArchFindMember(const char *, const char *, 169static FILE *ArchFindMember(const char *, const char *,
173 struct ar_hdr *, const char *); 170 struct ar_hdr *, const char *);
174#if defined(__svr4__) || defined(__SVR4) || defined(__ELF__) 171#if defined(__svr4__) || defined(__SVR4) || defined(__ELF__)
175#define SVR4ARCHIVES 172#define SVR4ARCHIVES
176static int ArchSVR4Entry(Arch *, char *, size_t, FILE *); 173static int ArchSVR4Entry(Arch *, char *, size_t, FILE *);
177#endif 174#endif
178 175
179#ifdef CLEANUP 176#ifdef CLEANUP
180/*- 
181 *----------------------------------------------------------------------- 
182 * ArchFree -- 
183 * Free memory used by an archive 
184 * 
185 * Results: 
186 * None. 
187 * 
188 * Side Effects: 
189 * None. 
190 * 
191 *----------------------------------------------------------------------- 
192 */ 
193static void 177static void
194ArchFree(void *ap) 178ArchFree(void *ap)
195{ 179{
196 Arch *a = (Arch *)ap; 180 Arch *a = (Arch *)ap;
197 Hash_Search search; 181 Hash_Search search;
198 Hash_Entry *entry; 182 Hash_Entry *entry;
199 183
200 /* Free memory from hash entries */ 184 /* Free memory from hash entries */
201 for (entry = Hash_EnumFirst(&a->members, &search); 185 for (entry = Hash_EnumFirst(&a->members, &search);
202 entry != NULL; 186 entry != NULL;
203 entry = Hash_EnumNext(&search)) 187 entry = Hash_EnumNext(&search))
204 free(Hash_GetValue(entry)); 188 free(Hash_GetValue(entry));
205 189
206 free(a->name); 190 free(a->name);
207 free(a->fnametab); 191 free(a->fnametab);
208 Hash_DeleteTable(&a->members); 192 Hash_DeleteTable(&a->members);
209 free(a); 193 free(a);
210} 194}
211#endif 195#endif
212 196
213 197
214 
215/*- 198/*-
216 *----------------------------------------------------------------------- 199 *-----------------------------------------------------------------------
217 * Arch_ParseArchive -- 200 * Arch_ParseArchive --
218 * Parse the archive specification in the given line and find/create 201 * Parse the archive specification in the given line and find/create
219 * the nodes for the specified archive members, placing their nodes 202 * the nodes for the specified archive members, placing their nodes
220 * on the given list. 203 * on the given list.
221 * 204 *
222 * Input: 205 * Input:
223 * linePtr Pointer to start of specification 206 * linePtr Pointer to start of specification
224 * nodeLst Lst on which to place the nodes 207 * nodeLst Lst on which to place the nodes
225 * ctxt Context in which to expand variables 208 * ctxt Context in which to expand variables
226 * 209 *
227 * Results: 210 * Results:
228 * TRUE if it was a valid specification. The linePtr is updated 211 * TRUE if it was a valid specification. The linePtr is updated
229 * to point to the first non-space after the archive spec. The 212 * to point to the first non-space after the archive spec. The
230 * nodes for the members are placed on the given list. 213 * nodes for the members are placed on the given list.
231 * 
232 * Side Effects: 
233 * Some nodes may be created. The given list is extended. 
234 * 
235 *----------------------------------------------------------------------- 214 *-----------------------------------------------------------------------
236 */ 215 */
237Boolean 216Boolean
238Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) 217Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
239{ 218{
240 char *cp; /* Pointer into line */ 219 char *cp; /* Pointer into line */
241 GNode *gn; /* New node */ 220 GNode *gn; /* New node */
242 char *libName; /* Library-part of specification */ 221 char *libName; /* Library-part of specification */
243 char *memName; /* Member-part of specification */ 222 char *memName; /* Member-part of specification */
244 char saveChar; /* Ending delimiter of member-name */ 223 char saveChar; /* Ending delimiter of member-name */
245 Boolean subLibName; /* TRUE if libName should have/had 224 Boolean subLibName; /* TRUE if libName should have/had
246 * variable substitution performed on it */ 225 * variable substitution performed on it */
247 226
248 libName = *linePtr; 227 libName = *linePtr;
249 228
250 subLibName = FALSE; 229 subLibName = FALSE;
251 230
252 for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { 231 for (cp = libName; *cp != '(' && *cp != '\0'; cp++) {
253 if (*cp == '$') { 232 if (*cp == '$') {
254 /* 233 /*
255 * Variable spec, so call the Var module to parse the puppy 234 * Variable spec, so call the Var module to parse the puppy
256 * so we can safely advance beyond it... 235 * so we can safely advance beyond it...
257 */ 236 */
258 int length; 237 int length;
259 void *freeIt; 238 void *freeIt;
260 const char *result; 239 const char *result;
261 240
262 result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, 241 result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES,
263 &length, &freeIt); 242 &length, &freeIt);
264 free(freeIt); 243 free(freeIt);
265 244
266 if (result == var_Error) { 245 if (result == var_Error) {
267 return FALSE; 246 return FALSE;
268 } else { 247 } else {
269 subLibName = TRUE; 248 subLibName = TRUE;
270 } 249 }
271 250
272 cp += length-1; 251 cp += length-1;
273 } 252 }
274 } 253 }
275 254
276 *cp++ = '\0'; 255 *cp++ = '\0';
277 if (subLibName) { 256 if (subLibName) {
278 libName = Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES); 257 libName = Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES);
279 } 258 }
280 259
281 260
282 for (;;) { 261 for (;;) {
283 /* 262 /*
284 * First skip to the start of the member's name, mark that 263 * First skip to the start of the member's name, mark that
285 * place and skip to the end of it (either white-space or 264 * place and skip to the end of it (either white-space or
286 * a close paren). 265 * a close paren).
287 */ 266 */
288 Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ 267 Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */
289 268
290 while (*cp != '\0' && *cp != ')' && isspace ((unsigned char)*cp)) { 269 while (*cp != '\0' && *cp != ')' && isspace ((unsigned char)*cp)) {
291 cp++; 270 cp++;
292 } 271 }
293 memName = cp; 272 memName = cp;
294 while (*cp != '\0' && *cp != ')' && !isspace ((unsigned char)*cp)) { 273 while (*cp != '\0' && *cp != ')' && !isspace ((unsigned char)*cp)) {
295 if (*cp == '$') { 274 if (*cp == '$') {
296 /* 275 /*
297 * Variable spec, so call the Var module to parse the puppy 276 * Variable spec, so call the Var module to parse the puppy
298 * so we can safely advance beyond it... 277 * so we can safely advance beyond it...
299 */ 278 */
300 int length; 279 int length;
301 void *freeIt; 280 void *freeIt;
302 const char *result; 281 const char *result;
303 282
304 result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, 283 result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES,
305 &length, &freeIt); 284 &length, &freeIt);
306 free(freeIt); 285 free(freeIt);
307 286
308 if (result == var_Error) { 287 if (result == var_Error) {
309 return FALSE; 288 return FALSE;
310 } else { 289 } else {
311 doSubst = TRUE; 290 doSubst = TRUE;
312 } 291 }
313 292
314 cp += length; 293 cp += length;
315 } else { 294 } else {
316 cp++; 295 cp++;
317 } 296 }
318 } 297 }
319 298
320 /* 299 /*
321 * If the specification ends without a closing parenthesis, 300 * If the specification ends without a closing parenthesis,
322 * chances are there's something wrong (like a missing backslash), 301 * chances are there's something wrong (like a missing backslash),
323 * so it's better to return failure than allow such things to happen 302 * so it's better to return failure than allow such things to happen
324 */ 303 */
325 if (*cp == '\0') { 304 if (*cp == '\0') {
326 printf("No closing parenthesis in archive specification\n"); 305 printf("No closing parenthesis in archive specification\n");
327 return FALSE; 306 return FALSE;
328 } 307 }
329 308
330 /* 309 /*
331 * If we didn't move anywhere, we must be done 310 * If we didn't move anywhere, we must be done
332 */ 311 */
333 if (cp == memName) { 312 if (cp == memName) {
334 break; 313 break;
335 } 314 }
336 315
337 saveChar = *cp; 316 saveChar = *cp;
338 *cp = '\0'; 317 *cp = '\0';
339 318
340 /* 319 /*
341 * XXX: This should be taken care of intelligently by 320 * XXX: This should be taken care of intelligently by
342 * SuffExpandChildren, both for the archive and the member portions. 321 * SuffExpandChildren, both for the archive and the member portions.
343 */ 322 */
344 /* 323 /*
345 * If member contains variables, try and substitute for them. 324 * If member contains variables, try and substitute for them.
346 * This will slow down archive specs with dynamic sources, of course, 325 * This will slow down archive specs with dynamic sources, of course,
347 * since we'll be (non-)substituting them three times, but them's 326 * since we'll be (non-)substituting them three times, but them's
348 * the breaks -- we need to do this since SuffExpandChildren calls 327 * the breaks -- we need to do this since SuffExpandChildren calls
349 * us, otherwise we could assume the thing would be taken care of 328 * us, otherwise we could assume the thing would be taken care of
350 * later. 329 * later.
351 */ 330 */
352 if (doSubst) { 331 if (doSubst) {
353 char *buf; 332 char *buf;
354 char *sacrifice; 333 char *sacrifice;
355 char *oldMemName = memName; 334 char *oldMemName = memName;
356 335
357 memName = Var_Subst(memName, ctxt, VARE_UNDEFERR | VARE_WANTRES); 336 memName = Var_Subst(memName, ctxt, VARE_UNDEFERR | VARE_WANTRES);
358 337
359 /* 338 /*
360 * Now form an archive spec and recurse to deal with nested 339 * Now form an archive spec and recurse to deal with nested
361 * variables and multi-word variable values.... The results 340 * variables and multi-word variable values.... The results
362 * are just placed at the end of the nodeLst we're returning. 341 * are just placed at the end of the nodeLst we're returning.
363 */ 342 */
364 buf = sacrifice = str_concat4(libName, "(", memName, ")"); 343 buf = sacrifice = str_concat4(libName, "(", memName, ")");
365 344
366 if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { 345 if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) {
367 /* 346 /*
368 * Must contain dynamic sources, so we can't deal with it now. 347 * Must contain dynamic sources, so we can't deal with it now.
369 * Just create an ARCHV node for the thing and let 348 * Just create an ARCHV node for the thing and let
370 * SuffExpandChildren handle it... 349 * SuffExpandChildren handle it...
371 */ 350 */
372 gn = Targ_FindNode(buf, TARG_CREATE); 351 gn = Targ_FindNode(buf, TARG_CREATE);
373 352
374 if (gn == NULL) { 353 if (gn == NULL) {
375 free(buf); 354 free(buf);
376 return FALSE; 355 return FALSE;
377 } else { 356 } else {
378 gn->type |= OP_ARCHV; 357 gn->type |= OP_ARCHV;
379 Lst_Append(nodeLst, gn); 358 Lst_Append(nodeLst, gn);
380 } 359 }
381 } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) { 360 } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) {
382 /* 361 /*
383 * Error in nested call -- free buffer and return FAILURE 362 * Error in nested call -- free buffer and return FAILURE
384 * ourselves. 363 * ourselves.
385 */ 364 */
386 free(buf); 365 free(buf);
387 return FALSE; 366 return FALSE;
388 } 367 }
389 /* 368 /*
390 * Free buffer and continue with our work. 369 * Free buffer and continue with our work.
391 */ 370 */
392 free(buf); 371 free(buf);
393 } else if (Dir_HasWildcards(memName)) { 372 } else if (Dir_HasWildcards(memName)) {
394 Lst members = Lst_Init(); 373 Lst members = Lst_Init();
395 Buffer nameBuf; 374 Buffer nameBuf;
396 375
397 Buf_Init(&nameBuf, 0); 376 Buf_Init(&nameBuf, 0);
398 Dir_Expand(memName, dirSearchPath, members); 377 Dir_Expand(memName, dirSearchPath, members);
399 while (!Lst_IsEmpty(members)) { 378 while (!Lst_IsEmpty(members)) {
400 char *member = Lst_Dequeue(members); 379 char *member = Lst_Dequeue(members);
401 380
402 Buf_Empty(&nameBuf); 381 Buf_Empty(&nameBuf);
403 Buf_AddStr(&nameBuf, libName); 382 Buf_AddStr(&nameBuf, libName);
404 Buf_AddStr(&nameBuf, "("); 383 Buf_AddStr(&nameBuf, "(");
405 Buf_AddStr(&nameBuf, member); 384 Buf_AddStr(&nameBuf, member);
406 Buf_AddStr(&nameBuf, ")"); 385 Buf_AddStr(&nameBuf, ")");
407 free(member); 386 free(member);
408 387
409 gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); 388 gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE);
410 if (gn == NULL) { 389 if (gn == NULL) {
411 Buf_Destroy(&nameBuf, TRUE); 390 Buf_Destroy(&nameBuf, TRUE);
412 return FALSE; 391 return FALSE;
413 } else { 392 } else {
414 /* 393 /*
415 * We've found the node, but have to make sure the rest of 394 * We've found the node, but have to make sure the rest of
416 * the world knows it's an archive member, without having 395 * the world knows it's an archive member, without having
417 * to constantly check for parentheses, so we type the 396 * to constantly check for parentheses, so we type the
418 * thing with the OP_ARCHV bit before we place it on the 397 * thing with the OP_ARCHV bit before we place it on the
419 * end of the provided list. 398 * end of the provided list.
420 */ 399 */
421 gn->type |= OP_ARCHV; 400 gn->type |= OP_ARCHV;
422 Lst_Append(nodeLst, gn); 401 Lst_Append(nodeLst, gn);
423 } 402 }
424 } 403 }
425 Lst_Free(members); 404 Lst_Free(members);
426 Buf_Destroy(&nameBuf, TRUE); 405 Buf_Destroy(&nameBuf, TRUE);
427 } else { 406 } else {
428 Buffer nameBuf; 407 Buffer nameBuf;
429 408
430 Buf_Init(&nameBuf, 0); 409 Buf_Init(&nameBuf, 0);
431 Buf_AddStr(&nameBuf, libName); 410 Buf_AddStr(&nameBuf, libName);
432 Buf_AddStr(&nameBuf, "("); 411 Buf_AddStr(&nameBuf, "(");
433 Buf_AddStr(&nameBuf, memName); 412 Buf_AddStr(&nameBuf, memName);
434 Buf_AddStr(&nameBuf, ")"); 413 Buf_AddStr(&nameBuf, ")");
435 414
436 gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); 415 gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE);
437 Buf_Destroy(&nameBuf, TRUE); 416 Buf_Destroy(&nameBuf, TRUE);
438 if (gn == NULL) { 417 if (gn == NULL) {
439 return FALSE; 418 return FALSE;
440 } else { 419 } else {
441 /* 420 /*
442 * We've found the node, but have to make sure the rest of the 421 * We've found the node, but have to make sure the rest of the
443 * world knows it's an archive member, without having to 422 * world knows it's an archive member, without having to
444 * constantly check for parentheses, so we type the thing with 423 * constantly check for parentheses, so we type the thing with
445 * the OP_ARCHV bit before we place it on the end of the 424 * the OP_ARCHV bit before we place it on the end of the
446 * provided list. 425 * provided list.
447 */ 426 */
448 gn->type |= OP_ARCHV; 427 gn->type |= OP_ARCHV;
449 Lst_Append(nodeLst, gn); 428 Lst_Append(nodeLst, gn);
450 } 429 }
451 } 430 }
452 if (doSubst) { 431 if (doSubst) {
453 free(memName); 432 free(memName);
454 } 433 }
455 434
456 *cp = saveChar; 435 *cp = saveChar;
457 } 436 }
458 437
459 /* 438 /*
460 * If substituted libName, free it now, since we need it no longer. 439 * If substituted libName, free it now, since we need it no longer.
461 */ 440 */
462 if (subLibName) { 441 if (subLibName) {
463 free(libName); 442 free(libName);
464 } 443 }
465 444
466 /* 445 /*
467 * We promised the pointer would be set up at the next non-space, so 446 * We promised the pointer would be set up at the next non-space, so
468 * we must advance cp there before setting *linePtr... (note that on 447 * we must advance cp there before setting *linePtr... (note that on
469 * entrance to the loop, cp is guaranteed to point at a ')') 448 * entrance to the loop, cp is guaranteed to point at a ')')
470 */ 449 */
471 do { 450 do {
472 cp++; 451 cp++;
473 } while (*cp != '\0' && isspace ((unsigned char)*cp)); 452 } while (*cp != '\0' && isspace ((unsigned char)*cp));
474 453
475 *linePtr = cp; 454 *linePtr = cp;
476 return TRUE; 455 return TRUE;
477} 456}
478 457
479/*- 458/*-
480 *----------------------------------------------------------------------- 459 *-----------------------------------------------------------------------
481 * ArchFindArchive -- 460 * ArchFindArchive --
482 * See if the given archive is the one we are looking for. Called 461 * See if the given archive is the one we are looking for. Called
483 * From ArchStatMember and ArchFindMember via Lst_Find. 462 * From ArchStatMember and ArchFindMember via Lst_Find.
484 * 463 *
485 * Input: 464 * Input:
486 * ar Current list element 465 * ar Current list element
487 * archName Name we want 466 * archName Name we want
488 * 467 *
489 * Results: 468 * Results:
490 * 0 if it is, non-zero if it isn't. 469 * 0 if it is, non-zero if it isn't.
491 * 
492 * Side Effects: 
493 * None. 
494 * 
495 *----------------------------------------------------------------------- 470 *-----------------------------------------------------------------------
496 */ 471 */
497static int 472static int
498ArchFindArchive(const void *ar, const void *archName) 473ArchFindArchive(const void *ar, const void *archName)
499{ 474{
500 return strcmp(archName, ((const Arch *)ar)->name); 475 return strcmp(archName, ((const Arch *)ar)->name);
501} 476}
502 477
503/*- 478/*-
504 *----------------------------------------------------------------------- 479 *-----------------------------------------------------------------------
505 * ArchStatMember -- 480 * ArchStatMember --
506 * Locate a member of an archive, given the path of the archive and 481 * Locate a member of an archive, given the path of the archive and
507 * the path of the desired member. 482 * the path of the desired member.
508 * 483 *
509 * Input: 484 * Input:
510 * archive Path to the archive 485 * archive Path to the archive
511 * member Name of member. If it is a path, only the last 486 * member Name of member. If it is a path, only the last
512 * component is used. 487 * component is used.
513 * hash TRUE if archive should be hashed if not already so. 488 * hash TRUE if archive should be hashed if not already so.
514 * 489 *
515 * Results: 490 * Results:
516 * A pointer to the current struct ar_hdr structure for the member. Note 491 * A pointer to the current struct ar_hdr structure for the member. Note
517 * That no position is returned, so this is not useful for touching 492 * That no position is returned, so this is not useful for touching
518 * archive members. This is mostly because we have no assurances that 493 * archive members. This is mostly because we have no assurances that
519 * The archive will remain constant after we read all the headers, so 494 * The archive will remain constant after we read all the headers, so
520 * there's not much point in remembering the position... 495 * there's not much point in remembering the position...
521 * 
522 * Side Effects: 
523 * 
524 *----------------------------------------------------------------------- 496 *-----------------------------------------------------------------------
525 */ 497 */
526static struct ar_hdr * 498static struct ar_hdr *
527ArchStatMember(const char *archive, const char *member, Boolean hash) 499ArchStatMember(const char *archive, const char *member, Boolean hash)
528{ 500{
529#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) 501#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1)
530 FILE * arch; /* Stream to archive */ 502 FILE * arch; /* Stream to archive */
531 size_t size; /* Size of archive member */ 503 size_t size; /* Size of archive member */
532 char magic[SARMAG]; 504 char magic[SARMAG];
533 LstNode ln; /* Lst member containing archive descriptor */ 505 LstNode ln; /* Lst member containing archive descriptor */
534 Arch *ar; /* Archive descriptor */ 506 Arch *ar; /* Archive descriptor */
535 Hash_Entry *he; /* Entry containing member's description */ 507 Hash_Entry *he; /* Entry containing member's description */
536 struct ar_hdr arh; /* archive-member header for reading archive */ 508 struct ar_hdr arh; /* archive-member header for reading archive */
537 char memName[MAXPATHLEN+1]; 509 char memName[MAXPATHLEN+1];
538 /* Current member name while hashing. */ 510 /* Current member name while hashing. */
539 511
540 /* 512 /*
541 * Because of space constraints and similar things, files are archived 513 * Because of space constraints and similar things, files are archived
542 * using their final path components, not the entire thing, so we need 514 * using their final path components, not the entire thing, so we need
543 * to point 'member' to the final component, if there is one, to make 515 * to point 'member' to the final component, if there is one, to make
544 * the comparisons easier... 516 * the comparisons easier...
545 */ 517 */
546 const char *base = strrchr(member, '/'); 518 const char *base = strrchr(member, '/');
547 if (base != NULL) { 519 if (base != NULL) {
548 member = base + 1; 520 member = base + 1;
549 } 521 }
550 522
551 ln = Lst_Find(archives, ArchFindArchive, archive); 523 ln = Lst_Find(archives, ArchFindArchive, archive);
552 if (ln != NULL) { 524 if (ln != NULL) {
553 ar = Lst_Datum(ln); 525 ar = Lst_Datum(ln);
554 526
555 he = Hash_FindEntry(&ar->members, member); 527 he = Hash_FindEntry(&ar->members, member);
556 528
557 if (he != NULL) { 529 if (he != NULL) {
558 return (struct ar_hdr *)Hash_GetValue(he); 530 return (struct ar_hdr *)Hash_GetValue(he);
559 } else { 531 } else {
560 /* Try truncated name */ 532 /* Try truncated name */
561 char copy[AR_MAX_NAME_LEN+1]; 533 char copy[AR_MAX_NAME_LEN+1];
562 size_t len = strlen(member); 534 size_t len = strlen(member);
563 535
564 if (len > AR_MAX_NAME_LEN) { 536 if (len > AR_MAX_NAME_LEN) {
565 len = AR_MAX_NAME_LEN; 537 len = AR_MAX_NAME_LEN;
566 snprintf(copy, sizeof copy, "%s", member); 538 snprintf(copy, sizeof copy, "%s", member);
567 } 539 }
568 if ((he = Hash_FindEntry(&ar->members, copy)) != NULL) 540 if ((he = Hash_FindEntry(&ar->members, copy)) != NULL)
569 return (struct ar_hdr *)Hash_GetValue(he); 541 return (struct ar_hdr *)Hash_GetValue(he);
570 return NULL; 542 return NULL;
571 } 543 }
572 } 544 }
573 545
574 if (!hash) { 546 if (!hash) {
575 /* 547 /*
576 * Caller doesn't want the thing hashed, just use ArchFindMember 548 * Caller doesn't want the thing hashed, just use ArchFindMember
577 * to read the header for the member out and close down the stream 549 * to read the header for the member out and close down the stream
578 * again. Since the archive is not to be hashed, we assume there's 550 * again. Since the archive is not to be hashed, we assume there's
579 * no need to allocate extra room for the header we're returning, 551 * no need to allocate extra room for the header we're returning,
580 * so just declare it static. 552 * so just declare it static.
581 */ 553 */
582 static struct ar_hdr sarh; 554 static struct ar_hdr sarh;
583 555
584 arch = ArchFindMember(archive, member, &sarh, "r"); 556 arch = ArchFindMember(archive, member, &sarh, "r");
585 557
586 if (arch == NULL) { 558 if (arch == NULL) {
587 return NULL; 559 return NULL;
588 } else { 560 } else {
589 fclose(arch); 561 fclose(arch);
590 return &sarh; 562 return &sarh;
591 } 563 }
592 } 564 }
593 565
594 /* 566 /*
595 * We don't have this archive on the list yet, so we want to find out 567 * We don't have this archive on the list yet, so we want to find out
596 * everything that's in it and cache it so we can get at it quickly. 568 * everything that's in it and cache it so we can get at it quickly.
597 */ 569 */
598 arch = fopen(archive, "r"); 570 arch = fopen(archive, "r");
599 if (arch == NULL) { 571 if (arch == NULL) {
600 return NULL; 572 return NULL;
601 } 573 }
602 574
603 /* 575 /*
604 * We use the ARMAG string to make sure this is an archive we 576 * We use the ARMAG string to make sure this is an archive we
605 * can handle... 577 * can handle...
606 */ 578 */
607 if ((fread(magic, SARMAG, 1, arch) != 1) || 579 if ((fread(magic, SARMAG, 1, arch) != 1) ||
608 (strncmp(magic, ARMAG, SARMAG) != 0)) { 580 (strncmp(magic, ARMAG, SARMAG) != 0)) {
609 fclose(arch); 581 fclose(arch);
610 return NULL; 582 return NULL;
611 } 583 }
612 584
613 ar = bmake_malloc(sizeof(Arch)); 585 ar = bmake_malloc(sizeof(Arch));
614 ar->name = bmake_strdup(archive); 586 ar->name = bmake_strdup(archive);
615 ar->fnametab = NULL; 587 ar->fnametab = NULL;
616 ar->fnamesize = 0; 588 ar->fnamesize = 0;
617 Hash_InitTable(&ar->members, -1); 589 Hash_InitTable(&ar->members, -1);
618 memName[AR_MAX_NAME_LEN] = '\0'; 590 memName[AR_MAX_NAME_LEN] = '\0';
619 591
620 while (fread((char *)&arh, sizeof(struct ar_hdr), 1, arch) == 1) { 592 while (fread((char *)&arh, sizeof(struct ar_hdr), 1, arch) == 1) {
621 if (strncmp( arh.ar_fmag, ARFMAG, sizeof(arh.ar_fmag)) != 0) { 593 if (strncmp( arh.ar_fmag, ARFMAG, sizeof(arh.ar_fmag)) != 0) {
622 /* 594 /*
623 * The header is bogus, so the archive is bad 595 * The header is bogus, so the archive is bad
624 * and there's no way we can recover... 596 * and there's no way we can recover...
625 */ 597 */
626 goto badarch; 598 goto badarch;
627 } else { 599 } else {
628 char *nameend; 600 char *nameend;
629 601
630 /* 602 /*
631 * We need to advance the stream's pointer to the start of the 603 * We need to advance the stream's pointer to the start of the
632 * next header. Files are padded with newlines to an even-byte 604 * next header. Files are padded with newlines to an even-byte
633 * boundary, so we need to extract the size of the file from the 605 * boundary, so we need to extract the size of the file from the
634 * 'size' field of the header and round it up during the seek. 606 * 'size' field of the header and round it up during the seek.
635 */ 607 */
636 arh.ar_size[sizeof(arh.ar_size)-1] = '\0'; 608 arh.ar_size[sizeof(arh.ar_size)-1] = '\0';
637 size = (size_t)strtol(arh.ar_size, NULL, 10); 609 size = (size_t)strtol(arh.ar_size, NULL, 10);
638 610
639 memcpy(memName, arh.ar_name, sizeof(arh.ar_name)); 611 memcpy(memName, arh.ar_name, sizeof(arh.ar_name));
640 nameend = memName + AR_MAX_NAME_LEN; 612 nameend = memName + AR_MAX_NAME_LEN;
641 while (*nameend == ' ') { 613 while (*nameend == ' ') {
642 nameend--; 614 nameend--;
643 } 615 }
644 nameend[1] = '\0'; 616 nameend[1] = '\0';
645 617
646#ifdef SVR4ARCHIVES 618#ifdef SVR4ARCHIVES
647 /* 619 /*
648 * svr4 names are slash terminated. Also svr4 extended AR format. 620 * svr4 names are slash terminated. Also svr4 extended AR format.
649 */ 621 */
650 if (memName[0] == '/') { 622 if (memName[0] == '/') {
651 /* 623 /*
652 * svr4 magic mode; handle it 624 * svr4 magic mode; handle it
653 */ 625 */
654 switch (ArchSVR4Entry(ar, memName, size, arch)) { 626 switch (ArchSVR4Entry(ar, memName, size, arch)) {
655 case -1: /* Invalid data */ 627 case -1: /* Invalid data */
656 goto badarch; 628 goto badarch;
657 case 0: /* List of files entry */ 629 case 0: /* List of files entry */
658 continue; 630 continue;
659 default: /* Got the entry */ 631 default: /* Got the entry */
660 break; 632 break;
661 } 633 }
662 } 634 }
663 else { 635 else {
664 if (nameend[0] == '/') 636 if (nameend[0] == '/')
665 nameend[0] = '\0'; 637 nameend[0] = '\0';
666 } 638 }
667#endif 639#endif
668 640
669#ifdef AR_EFMT1 641#ifdef AR_EFMT1
670 /* 642 /*
671 * BSD 4.4 extended AR format: #1/<namelen>, with name as the 643 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
672 * first <namelen> bytes of the file 644 * first <namelen> bytes of the file
673 */ 645 */
674 if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && 646 if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
675 isdigit((unsigned char)memName[sizeof(AR_EFMT1) - 1])) { 647 isdigit((unsigned char)memName[sizeof(AR_EFMT1) - 1])) {
676 648
677 int elen = atoi(&memName[sizeof(AR_EFMT1)-1]); 649 int elen = atoi(&memName[sizeof(AR_EFMT1)-1]);
678 650
679 if ((unsigned int)elen > MAXPATHLEN) 651 if ((unsigned int)elen > MAXPATHLEN)
680 goto badarch; 652 goto badarch;
681 if (fread(memName, (size_t)elen, 1, arch) != 1) 653 if (fread(memName, (size_t)elen, 1, arch) != 1)
682 goto badarch; 654 goto badarch;
683 memName[elen] = '\0'; 655 memName[elen] = '\0';
684 if (fseek(arch, -elen, SEEK_CUR) != 0) 656 if (fseek(arch, -elen, SEEK_CUR) != 0)
685 goto badarch; 657 goto badarch;
686 if (DEBUG(ARCH) || DEBUG(MAKE)) { 658 if (DEBUG(ARCH) || DEBUG(MAKE)) {
687 fprintf(debug_file, "ArchStat: Extended format entry for %s\n", memName); 659 fprintf(debug_file, "ArchStat: Extended format entry for %s\n", memName);
688 } 660 }
689 } 661 }
690#endif 662#endif
691 663
692 he = Hash_CreateEntry(&ar->members, memName, NULL); 664 he = Hash_CreateEntry(&ar->members, memName, NULL);
693 Hash_SetValue(he, bmake_malloc(sizeof(struct ar_hdr))); 665 Hash_SetValue(he, bmake_malloc(sizeof(struct ar_hdr)));
694 memcpy(Hash_GetValue(he), &arh, sizeof(struct ar_hdr)); 666 memcpy(Hash_GetValue(he), &arh, sizeof(struct ar_hdr));
695 } 667 }
696 if (fseek(arch, ((long)size + 1) & ~1, SEEK_CUR) != 0) 668 if (fseek(arch, ((long)size + 1) & ~1, SEEK_CUR) != 0)
697 goto badarch; 669 goto badarch;
698 } 670 }
699 671
700 fclose(arch); 672 fclose(arch);
701 673
702 Lst_Append(archives, ar); 674 Lst_Append(archives, ar);
703 675
704 /* 676 /*
705 * Now that the archive has been read and cached, we can look into 677 * Now that the archive has been read and cached, we can look into
706 * the hash table to find the desired member's header. 678 * the hash table to find the desired member's header.
707 */ 679 */
708 he = Hash_FindEntry(&ar->members, member); 680 he = Hash_FindEntry(&ar->members, member);
709 681
710 if (he != NULL) { 682 if (he != NULL) {
711 return (struct ar_hdr *)Hash_GetValue(he); 683 return (struct ar_hdr *)Hash_GetValue(he);
712 } else { 684 } else {
713 return NULL; 685 return NULL;
714 } 686 }
715 687
716badarch: 688badarch:
717 fclose(arch); 689 fclose(arch);
718 Hash_DeleteTable(&ar->members); 690 Hash_DeleteTable(&ar->members);
719 free(ar->fnametab); 691 free(ar->fnametab);
720 free(ar); 692 free(ar);
721 return NULL; 693 return NULL;
722} 694}
723 695
724#ifdef SVR4ARCHIVES 696#ifdef SVR4ARCHIVES
725/*- 697/*-
726 *----------------------------------------------------------------------- 698 *-----------------------------------------------------------------------
727 * ArchSVR4Entry -- 699 * ArchSVR4Entry --
728 * Parse an SVR4 style entry that begins with a slash. 700 * Parse an SVR4 style entry that begins with a slash.
729 * If it is "//", then load the table of filenames 701 * If it is "//", then load the table of filenames
730 * If it is "/<offset>", then try to substitute the long file name 702 * If it is "/<offset>", then try to substitute the long file name
731 * from offset of a table previously read. 703 * from offset of a table previously read.
 704 * If a table is read, the file pointer is moved to the next archive
 705 * member.
732 * 706 *
733 * Results: 707 * Results:
734 * -1: Bad data in archive 708 * -1: Bad data in archive
735 * 0: A table was loaded from the file 709 * 0: A table was loaded from the file
736 * 1: Name was successfully substituted from table 710 * 1: Name was successfully substituted from table
737 * 2: Name was not successfully substituted from table 711 * 2: Name was not successfully substituted from table
738 * 
739 * Side Effects: 
740 * If a table is read, the file pointer is moved to the next archive 
741 * member 
742 * 
743 *----------------------------------------------------------------------- 712 *-----------------------------------------------------------------------
744 */ 713 */
745static int 714static int
746ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch) 715ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
747{ 716{
748#define ARLONGNAMES1 "//" 717#define ARLONGNAMES1 "//"
749#define ARLONGNAMES2 "/ARFILENAMES" 718#define ARLONGNAMES2 "/ARFILENAMES"
750 size_t entry; 719 size_t entry;
751 char *ptr, *eptr; 720 char *ptr, *eptr;
752 721
753 if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || 722 if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 ||
754 strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { 723 strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) {
755 724
756 if (ar->fnametab != NULL) { 725 if (ar->fnametab != NULL) {
757 if (DEBUG(ARCH)) { 726 if (DEBUG(ARCH)) {
758 fprintf(debug_file, "Attempted to redefine an SVR4 name table\n"); 727 fprintf(debug_file, "Attempted to redefine an SVR4 name table\n");
759 } 728 }
760 return -1; 729 return -1;
761 } 730 }
762 731
763 /* 732 /*
764 * This is a table of archive names, so we build one for 733 * This is a table of archive names, so we build one for
765 * ourselves 734 * ourselves
766 */ 735 */
767 ar->fnametab = bmake_malloc(size); 736 ar->fnametab = bmake_malloc(size);
768 ar->fnamesize = size; 737 ar->fnamesize = size;
769 738
770 if (fread(ar->fnametab, size, 1, arch) != 1) { 739 if (fread(ar->fnametab, size, 1, arch) != 1) {
771 if (DEBUG(ARCH)) { 740 if (DEBUG(ARCH)) {
772 fprintf(debug_file, "Reading an SVR4 name table failed\n"); 741 fprintf(debug_file, "Reading an SVR4 name table failed\n");
773 } 742 }
774 return -1; 743 return -1;
775 } 744 }
776 eptr = ar->fnametab + size; 745 eptr = ar->fnametab + size;
777 for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++) 746 for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++)
778 switch (*ptr) { 747 switch (*ptr) {
779 case '/': 748 case '/':
780 entry++; 749 entry++;
781 *ptr = '\0'; 750 *ptr = '\0';
782 break; 751 break;
783 752
784 case '\n': 753 case '\n':
785 break; 754 break;
786 755
787 default: 756 default:
788 break; 757 break;
789 } 758 }
790 if (DEBUG(ARCH)) { 759 if (DEBUG(ARCH)) {
791 fprintf(debug_file, "Found svr4 archive name table with %lu entries\n", 760 fprintf(debug_file, "Found svr4 archive name table with %lu entries\n",
792 (unsigned long)entry); 761 (unsigned long)entry);
793 } 762 }
794 return 0; 763 return 0;
795 } 764 }
796 765
797 if (name[1] == ' ' || name[1] == '\0') 766 if (name[1] == ' ' || name[1] == '\0')
798 return 2; 767 return 2;
799 768
800 entry = (size_t)strtol(&name[1], &eptr, 0); 769 entry = (size_t)strtol(&name[1], &eptr, 0);
801 if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) { 770 if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) {
802 if (DEBUG(ARCH)) { 771 if (DEBUG(ARCH)) {
803 fprintf(debug_file, "Could not parse SVR4 name %s\n", name); 772 fprintf(debug_file, "Could not parse SVR4 name %s\n", name);
804 } 773 }
805 return 2; 774 return 2;
806 } 775 }
807 if (entry >= ar->fnamesize) { 776 if (entry >= ar->fnamesize) {
808 if (DEBUG(ARCH)) { 777 if (DEBUG(ARCH)) {
809 fprintf(debug_file, "SVR4 entry offset %s is greater than %lu\n", 778 fprintf(debug_file, "SVR4 entry offset %s is greater than %lu\n",
810 name, (unsigned long)ar->fnamesize); 779 name, (unsigned long)ar->fnamesize);
811 } 780 }
812 return 2; 781 return 2;
813 } 782 }
814 783
815 if (DEBUG(ARCH)) { 784 if (DEBUG(ARCH)) {
816 fprintf(debug_file, "Replaced %s with %s\n", name, &ar->fnametab[entry]); 785 fprintf(debug_file, "Replaced %s with %s\n", name, &ar->fnametab[entry]);
817 } 786 }
818 787
819 snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]); 788 snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]);
820 return 1; 789 return 1;
821} 790}
822#endif 791#endif
823 792
824 793
825/*- 794/*-
826 *----------------------------------------------------------------------- 795 *-----------------------------------------------------------------------
827 * ArchFindMember -- 796 * ArchFindMember --
828 * Locate a member of an archive, given the path of the archive and 797 * Locate a member of an archive, given the path of the archive and
829 * the path of the desired member. If the archive is to be modified, 798 * the path of the desired member. If the archive is to be modified,
830 * the mode should be "r+", if not, it should be "r". 799 * the mode should be "r+", if not, it should be "r".
 800 * The passed struct ar_hdr structure is filled in.
831 * 801 *
832 * Input: 802 * Input:
833 * archive Path to the archive 803 * archive Path to the archive
834 * member Name of member. If it is a path, only the last 804 * member Name of member. If it is a path, only the last
835 * component is used. 805 * component is used.
836 * arhPtr Pointer to header structure to be filled in 806 * arhPtr Pointer to header structure to be filled in
837 * mode The mode for opening the stream 807 * mode The mode for opening the stream
838 * 808 *
839 * Results: 809 * Results:
840 * An FILE *, opened for reading and writing, positioned at the 810 * An FILE *, opened for reading and writing, positioned at the
841 * start of the member's struct ar_hdr, or NULL if the member was 811 * start of the member's struct ar_hdr, or NULL if the member was
842 * nonexistent. The current struct ar_hdr for member. 812 * nonexistent. The current struct ar_hdr for member.
843 * 
844 * Side Effects: 
845 * The passed struct ar_hdr structure is filled in. 
846 * 
847 *----------------------------------------------------------------------- 813 *-----------------------------------------------------------------------
848 */ 814 */
849static FILE * 815static FILE *
850ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr, 816ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr,
851 const char *mode) 817 const char *mode)
852{ 818{
853 FILE * arch; /* Stream to archive */ 819 FILE * arch; /* Stream to archive */
854 int size; /* Size of archive member */ 820 int size; /* Size of archive member */
855 char magic[SARMAG]; 821 char magic[SARMAG];
856 size_t len, tlen; 822 size_t len, tlen;
857 const char * base; 823 const char * base;
858 824
859 arch = fopen(archive, mode); 825 arch = fopen(archive, mode);
860 if (arch == NULL) { 826 if (arch == NULL) {
861 return NULL; 827 return NULL;
862 } 828 }
863 829
864 /* 830 /*
865 * We use the ARMAG string to make sure this is an archive we 831 * We use the ARMAG string to make sure this is an archive we
866 * can handle... 832 * can handle...
867 */ 833 */
868 if ((fread(magic, SARMAG, 1, arch) != 1) || 834 if ((fread(magic, SARMAG, 1, arch) != 1) ||
869 (strncmp(magic, ARMAG, SARMAG) != 0)) { 835 (strncmp(magic, ARMAG, SARMAG) != 0)) {
870 fclose(arch); 836 fclose(arch);
871 return NULL; 837 return NULL;
872 } 838 }
873 839
874 /* 840 /*
875 * Because of space constraints and similar things, files are archived 841 * Because of space constraints and similar things, files are archived
876 * using their final path components, not the entire thing, so we need 842 * using their final path components, not the entire thing, so we need
877 * to point 'member' to the final component, if there is one, to make 843 * to point 'member' to the final component, if there is one, to make
878 * the comparisons easier... 844 * the comparisons easier...
879 */ 845 */
880 base = strrchr(member, '/'); 846 base = strrchr(member, '/');
881 if (base != NULL) { 847 if (base != NULL) {
882 member = base + 1; 848 member = base + 1;
883 } 849 }
884 len = tlen = strlen(member); 850 len = tlen = strlen(member);
885 if (len > sizeof(arhPtr->ar_name)) { 851 if (len > sizeof(arhPtr->ar_name)) {
886 tlen = sizeof(arhPtr->ar_name); 852 tlen = sizeof(arhPtr->ar_name);
887 } 853 }
888 854
889 while (fread((char *)arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) { 855 while (fread((char *)arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) {
890 if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof(arhPtr->ar_fmag) ) != 0) { 856 if (strncmp(arhPtr->ar_fmag, ARFMAG, sizeof(arhPtr->ar_fmag) ) != 0) {
891 /* 857 /*
892 * The header is bogus, so the archive is bad 858 * The header is bogus, so the archive is bad
893 * and there's no way we can recover... 859 * and there's no way we can recover...
894 */ 860 */
895 fclose(arch); 861 fclose(arch);
896 return NULL; 862 return NULL;
897 } else if (strncmp(member, arhPtr->ar_name, tlen) == 0) { 863 } else if (strncmp(member, arhPtr->ar_name, tlen) == 0) {
898 /* 864 /*
899 * If the member's name doesn't take up the entire 'name' field, 865 * If the member's name doesn't take up the entire 'name' field,
900 * we have to be careful of matching prefixes. Names are space- 866 * we have to be careful of matching prefixes. Names are space-
901 * padded to the right, so if the character in 'name' at the end 867 * padded to the right, so if the character in 'name' at the end
902 * of the matched string is anything but a space, this isn't the 868 * of the matched string is anything but a space, this isn't the
903 * member we sought. 869 * member we sought.
904 */ 870 */
905 if (tlen != sizeof(arhPtr->ar_name) && arhPtr->ar_name[tlen] != ' '){ 871 if (tlen != sizeof(arhPtr->ar_name) && arhPtr->ar_name[tlen] != ' '){
906 goto skip; 872 goto skip;
907 } else { 873 } else {
908 /* 874 /*
909 * To make life easier, we reposition the file at the start 875 * To make life easier, we reposition the file at the start
910 * of the header we just read before we return the stream. 876 * of the header we just read before we return the stream.
911 * In a more general situation, it might be better to leave 877 * In a more general situation, it might be better to leave
912 * the file at the actual member, rather than its header, but 878 * the file at the actual member, rather than its header, but
913 * not here... 879 * not here...
914 */ 880 */
915 if (fseek(arch, -(long)sizeof(struct ar_hdr), SEEK_CUR) != 0) { 881 if (fseek(arch, -(long)sizeof(struct ar_hdr), SEEK_CUR) != 0) {
916 fclose(arch); 882 fclose(arch);
917 return NULL; 883 return NULL;
918 } 884 }
919 return arch; 885 return arch;
920 } 886 }
921 } else 887 } else
922#ifdef AR_EFMT1 888#ifdef AR_EFMT1
923 /* 889 /*
924 * BSD 4.4 extended AR format: #1/<namelen>, with name as the 890 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
925 * first <namelen> bytes of the file 891 * first <namelen> bytes of the file
926 */ 892 */
927 if (strncmp(arhPtr->ar_name, AR_EFMT1, 893 if (strncmp(arhPtr->ar_name, AR_EFMT1,
928 sizeof(AR_EFMT1) - 1) == 0 && 894 sizeof(AR_EFMT1) - 1) == 0 &&
929 isdigit((unsigned char)arhPtr->ar_name[sizeof(AR_EFMT1) - 1])) { 895 isdigit((unsigned char)arhPtr->ar_name[sizeof(AR_EFMT1) - 1])) {
930 896
931 int elen = atoi(&arhPtr->ar_name[sizeof(AR_EFMT1)-1]); 897 int elen = atoi(&arhPtr->ar_name[sizeof(AR_EFMT1)-1]);
932 char ename[MAXPATHLEN + 1]; 898 char ename[MAXPATHLEN + 1];
933 899
934 if ((unsigned int)elen > MAXPATHLEN) { 900 if ((unsigned int)elen > MAXPATHLEN) {
935 fclose(arch); 901 fclose(arch);
936 return NULL; 902 return NULL;
937 } 903 }
938 if (fread(ename, (size_t)elen, 1, arch) != 1) { 904 if (fread(ename, (size_t)elen, 1, arch) != 1) {
939 fclose(arch); 905 fclose(arch);
940 return NULL; 906 return NULL;
941 } 907 }
942 ename[elen] = '\0'; 908 ename[elen] = '\0';
943 if (DEBUG(ARCH) || DEBUG(MAKE)) { 909 if (DEBUG(ARCH) || DEBUG(MAKE)) {
944 fprintf(debug_file, "ArchFind: Extended format entry for %s\n", ename); 910 fprintf(debug_file, "ArchFind: Extended format entry for %s\n", ename);
945 } 911 }
946 if (strncmp(ename, member, len) == 0) { 912 if (strncmp(ename, member, len) == 0) {
947 /* Found as extended name */ 913 /* Found as extended name */
948 if (fseek(arch, -(long)sizeof(struct ar_hdr) - elen, 914 if (fseek(arch, -(long)sizeof(struct ar_hdr) - elen,
949 SEEK_CUR) != 0) { 915 SEEK_CUR) != 0) {
950 fclose(arch); 916 fclose(arch);
951 return NULL; 917 return NULL;
952 } 918 }
953 return arch; 919 return arch;
954 } 920 }
955 if (fseek(arch, -elen, SEEK_CUR) != 0) { 921 if (fseek(arch, -elen, SEEK_CUR) != 0) {
956 fclose(arch); 922 fclose(arch);
957 return NULL; 923 return NULL;
958 } 924 }
959 goto skip; 925 goto skip;
960 } else 926 } else
961#endif 927#endif
962 { 928 {
963skip: 929skip:
964 /* 930 /*
965 * This isn't the member we're after, so we need to advance the 931 * This isn't the member we're after, so we need to advance the
966 * stream's pointer to the start of the next header. Files are 932 * stream's pointer to the start of the next header. Files are
967 * padded with newlines to an even-byte boundary, so we need to 933 * padded with newlines to an even-byte boundary, so we need to
968 * extract the size of the file from the 'size' field of the 934 * extract the size of the file from the 'size' field of the
969 * header and round it up during the seek. 935 * header and round it up during the seek.
970 */ 936 */
971 arhPtr->ar_size[sizeof(arhPtr->ar_size)-1] = '\0'; 937 arhPtr->ar_size[sizeof(arhPtr->ar_size)-1] = '\0';
972 size = (int)strtol(arhPtr->ar_size, NULL, 10); 938 size = (int)strtol(arhPtr->ar_size, NULL, 10);
973 if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) { 939 if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) {
974 fclose(arch); 940 fclose(arch);
975 return NULL; 941 return NULL;
976 } 942 }
977 } 943 }
978 } 944 }
979 945
980 /* 946 /*
981 * We've looked everywhere, but the member is not to be found. Close the 947 * We've looked everywhere, but the member is not to be found. Close the
982 * archive and return NULL -- an error. 948 * archive and return NULL -- an error.
983 */ 949 */
984 fclose(arch); 950 fclose(arch);
985 return NULL; 951 return NULL;
986} 952}
987 953
988/*- 954/*-
989 *----------------------------------------------------------------------- 955 *-----------------------------------------------------------------------
990 * Arch_Touch -- 956 * Arch_Touch --
991 * Touch a member of an archive. 957 * Touch a member of an archive.
 958 * The modification time of the entire archive is also changed.
 959 * For a library, this could necessitate the re-ranlib'ing of the
 960 * whole thing.
992 * 961 *
993 * Input: 962 * Input:
994 * gn Node of member to touch 963 * gn Node of member to touch
995 * 964 *
996 * Results: 965 * Results:
997 * The 'time' field of the member's header is updated. 966 * The 'time' field of the member's header is updated.
998 * 
999 * Side Effects: 
1000 * The modification time of the entire archive is also changed. 
1001 * For a library, this could necessitate the re-ranlib'ing of the 
1002 * whole thing. 
1003 * 
1004 *----------------------------------------------------------------------- 967 *-----------------------------------------------------------------------
1005 */ 968 */
1006void 969void
1007Arch_Touch(GNode *gn) 970Arch_Touch(GNode *gn)
1008{ 971{
1009 FILE * arch; /* Stream open to archive, positioned properly */ 972 FILE * arch; /* Stream open to archive, positioned properly */
1010 struct ar_hdr arh; /* Current header describing member */ 973 struct ar_hdr arh; /* Current header describing member */
1011 char *p1, *p2; 974 char *p1, *p2;
1012 975
1013 arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1), 976 arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1),
1014 Var_Value(MEMBER, gn, &p2), 977 Var_Value(MEMBER, gn, &p2),
1015 &arh, "r+"); 978 &arh, "r+");
1016 979
1017 bmake_free(p1); 980 bmake_free(p1);
1018 bmake_free(p2); 981 bmake_free(p2);
1019 982
1020 snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); 983 snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now);
1021 984
1022 if (arch != NULL) { 985 if (arch != NULL) {
1023 (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); 986 (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch);
1024 fclose(arch); 987 fclose(arch);
1025 } 988 }
1026} 989}
1027 990
1028/*- 991/* Given a node which represents a library, touch the thing, making sure that
1029 *----------------------------------------------------------------------- 992 * the table of contents also is touched.
1030 * Arch_TouchLib -- 993 *
1031 * Given a node which represents a library, touch the thing, making 994 * Both the modification time of the library and of the RANLIBMAG member are
1032 * sure that the table of contents also is touched. 995 * set to 'now'.
1033 * 996 *
1034 * Input: 997 * Input:
1035 * gn The node of the library to touch 998 * gn The node of the library to touch
1036 * 
1037 * Results: 
1038 * None. 
1039 * 
1040 * Side Effects: 
1041 * Both the modification time of the library and of the RANLIBMAG 
1042 * member are set to 'now'. 
1043 * 
1044 *----------------------------------------------------------------------- 
1045 */ 999 */
1046void 1000void
1047Arch_TouchLib(GNode *gn) 1001Arch_TouchLib(GNode *gn)
1048{ 1002{
1049#ifdef RANLIBMAG 1003#ifdef RANLIBMAG
1050 FILE * arch; /* Stream open to archive */ 1004 FILE * arch; /* Stream open to archive */
1051 struct ar_hdr arh; /* Header describing table of contents */ 1005 struct ar_hdr arh; /* Header describing table of contents */
1052 struct utimbuf times; /* Times for utime() call */ 1006 struct utimbuf times; /* Times for utime() call */
1053 1007
1054 arch = ArchFindMember(gn->path, RANLIBMAG, &arh, "r+"); 1008 arch = ArchFindMember(gn->path, RANLIBMAG, &arh, "r+");
1055 snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now); 1009 snprintf(arh.ar_date, sizeof(arh.ar_date), "%-12ld", (long) now);
1056 1010
1057 if (arch != NULL) { 1011 if (arch != NULL) {
1058 (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); 1012 (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch);
1059 fclose(arch); 1013 fclose(arch);
1060 1014
1061 times.actime = times.modtime = now; 1015 times.actime = times.modtime = now;
1062 utime(gn->path, &times); 1016 utime(gn->path, &times);
1063 } 1017 }
1064#else 1018#else
1065 (void)gn; 1019 (void)gn;
1066#endif 1020#endif
1067} 1021}
1068 1022
1069/*- 1023/* Return the modification time of a member of an archive. The mtime field
1070 *----------------------------------------------------------------------- 1024 * of the given node is filled in with the value returned by the function.
1071 * Arch_MTime -- 
1072 * Return the modification time of a member of an archive. 
1073 * 1025 *
1074 * Input: 1026 * Input:
1075 * gn Node describing archive member 1027 * gn Node describing archive member
1076 * 
1077 * Results: 
1078 * The modification time(seconds). 
1079 * 
1080 * Side Effects: 
1081 * The mtime field of the given node is filled in with the value 
1082 * returned by the function. 
1083 * 
1084 *----------------------------------------------------------------------- 
1085 */ 1028 */
1086time_t 1029time_t
1087Arch_MTime(GNode *gn) 1030Arch_MTime(GNode *gn)
1088{ 1031{
1089 struct ar_hdr *arhPtr; /* Header of desired member */ 1032 struct ar_hdr *arhPtr; /* Header of desired member */
1090 time_t modTime; /* Modification time as an integer */ 1033 time_t modTime; /* Modification time as an integer */
1091 char *p1, *p2; 1034 char *p1, *p2;
1092 1035
1093 arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1), 1036 arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1),
1094 Var_Value(MEMBER, gn, &p2), 1037 Var_Value(MEMBER, gn, &p2),
1095 TRUE); 1038 TRUE);
1096 1039
1097 bmake_free(p1); 1040 bmake_free(p1);
1098 bmake_free(p2); 1041 bmake_free(p2);
1099 1042
1100 if (arhPtr != NULL) { 1043 if (arhPtr != NULL) {
1101 modTime = (time_t)strtol(arhPtr->ar_date, NULL, 10); 1044 modTime = (time_t)strtol(arhPtr->ar_date, NULL, 10);
1102 } else { 1045 } else {
1103 modTime = 0; 1046 modTime = 0;
1104 } 1047 }
1105 1048
1106 gn->mtime = modTime; 1049 gn->mtime = modTime;
1107 return modTime; 1050 return modTime;
1108} 1051}
1109 1052
1110/*- 1053/* Given a non-existent archive member's node, get its modification time from
1111 *----------------------------------------------------------------------- 1054 * its archived form, if it exists. gn->mtime is filled in as well. */
1112 * Arch_MemMTime -- 
1113 * Given a non-existent archive member's node, get its modification 
1114 * time from its archived form, if it exists. 
1115 * 
1116 * Results: 
1117 * The modification time. 
1118 * 
1119 * Side Effects: 
1120 * The mtime field is filled in. 
1121 * 
1122 *----------------------------------------------------------------------- 
1123 */ 
1124time_t 1055time_t
1125Arch_MemMTime(GNode *gn) 1056Arch_MemMTime(GNode *gn)
1126{ 1057{
1127 LstNode ln; 1058 LstNode ln;
1128 GNode *pgn; 1059 GNode *pgn;
1129 1060
1130 Lst_Open(gn->parents); 1061 Lst_Open(gn->parents);
1131 while ((ln = Lst_Next(gn->parents)) != NULL) { 1062 while ((ln = Lst_Next(gn->parents)) != NULL) {
1132 pgn = Lst_Datum(ln); 1063 pgn = Lst_Datum(ln);
1133 1064
1134 if (pgn->type & OP_ARCHV) { 1065 if (pgn->type & OP_ARCHV) {
1135 /* 1066 /*
1136 * If the parent is an archive specification and is being made 1067 * If the parent is an archive specification and is being made
1137 * and its member's name matches the name of the node we were 1068 * and its member's name matches the name of the node we were
1138 * given, record the modification time of the parent in the 1069 * given, record the modification time of the parent in the
1139 * child. We keep searching its parents in case some other 1070 * child. We keep searching its parents in case some other
1140 * parent requires this child to exist... 1071 * parent requires this child to exist...
1141 */ 1072 */
1142 const char *nameStart = strchr(pgn->name, '(') + 1; 1073 const char *nameStart = strchr(pgn->name, '(') + 1;
1143 const char *nameEnd = strchr(nameStart, ')'); 1074 const char *nameEnd = strchr(nameStart, ')');
1144 size_t nameLen = (size_t)(nameEnd - nameStart); 1075 size_t nameLen = (size_t)(nameEnd - nameStart);
1145 1076
1146 if ((pgn->flags & REMAKE) && 1077 if ((pgn->flags & REMAKE) &&
1147 strncmp(nameStart, gn->name, nameLen) == 0) { 1078 strncmp(nameStart, gn->name, nameLen) == 0) {
1148 gn->mtime = Arch_MTime(pgn); 1079 gn->mtime = Arch_MTime(pgn);
1149 } 1080 }
1150 } else if (pgn->flags & REMAKE) { 1081 } else if (pgn->flags & REMAKE) {
1151 /* 1082 /*
1152 * Something which isn't a library depends on the existence of 1083 * Something which isn't a library depends on the existence of
1153 * this target, so it needs to exist. 1084 * this target, so it needs to exist.
1154 */ 1085 */
1155 gn->mtime = 0; 1086 gn->mtime = 0;
1156 break; 1087 break;
1157 } 1088 }
1158 } 1089 }
1159 1090
1160 Lst_Close(gn->parents); 1091 Lst_Close(gn->parents);
1161 1092
1162 return gn->mtime; 1093 return gn->mtime;
1163} 1094}
1164 1095
1165/*- 1096/* Search for a library along the given search path.
1166 *----------------------------------------------------------------------- 1097 *
1167 * Arch_FindLib -- 1098 * The node's 'path' field is set to the found path (including the
1168 * Search for a library along the given search path. 1099 * actual file name, not -l...). If the system can handle the -L
 1100 * flag when linking (or we cannot find the library), we assume that
 1101 * the user has placed the .LIBS variable in the final linking
 1102 * command (or the linker will know where to find it) and set the
 1103 * TARGET variable for this node to be the node's name. Otherwise,
 1104 * we set the TARGET variable to be the full path of the library,
 1105 * as returned by Dir_FindFile.
1169 * 1106 *
1170 * Input: 1107 * Input:
1171 * gn Node of library to find 1108 * gn Node of library to find
1172 * path Search path 1109 * path Search path
1173 * 
1174 * Results: 
1175 * None. 
1176 * 
1177 * Side Effects: 
1178 * The node's 'path' field is set to the found path (including the 
1179 * actual file name, not -l...). If the system can handle the -L 
1180 * flag when linking (or we cannot find the library), we assume that 
1181 * the user has placed the .LIBRARIES variable in the final linking 
1182 * command (or the linker will know where to find it) and set the 
1183 * TARGET variable for this node to be the node's name. Otherwise, 
1184 * we set the TARGET variable to be the full path of the library, 
1185 * as returned by Dir_FindFile. 
1186 * 
1187 *----------------------------------------------------------------------- 
1188 */ 1110 */
1189void 1111void
1190Arch_FindLib(GNode *gn, Lst path) 1112Arch_FindLib(GNode *gn, Lst path)
1191{ 1113{
1192 char *libName; /* file name for archive */ 1114 char *libName; /* file name for archive */
1193 size_t sz = strlen(gn->name) + 6 - 2; 1115 size_t sz = strlen(gn->name) + 6 - 2;
1194 1116
1195 libName = bmake_malloc(sz); 1117 libName = bmake_malloc(sz);
1196 snprintf(libName, sz, "lib%s.a", &gn->name[2]); 1118 snprintf(libName, sz, "lib%s.a", &gn->name[2]);
1197 1119
1198 gn->path = Dir_FindFile(libName, path); 1120 gn->path = Dir_FindFile(libName, path);
1199 1121
1200 free(libName); 1122 free(libName);
1201 1123
1202#ifdef LIBRARIES 1124#ifdef LIBRARIES
1203 Var_Set(TARGET, gn->name, gn); 1125 Var_Set(TARGET, gn->name, gn);
1204#else 1126#else
1205 Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); 1127 Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn);
1206#endif /* LIBRARIES */ 1128#endif /* LIBRARIES */
1207} 1129}
1208 1130
1209/*- 1131/* Decide if a node with the OP_LIB attribute is out-of-date. Called from
1210 *----------------------------------------------------------------------- 1132 * Make_OODate to make its life easier.
1211 * Arch_LibOODate -- 1133 * The library will be hashed if it hasn't been already.
1212 * Decide if a node with the OP_LIB attribute is out-of-date. Called 1134 *
1213 * from Make_OODate to make its life easier. 1135 * There are several ways for a library to be out-of-date that are
1214 * 1136 * not available to ordinary files. In addition, there are ways
1215 * There are several ways for a library to be out-of-date that are 1137 * that are open to regular files that are not available to
1216 * not available to ordinary files. In addition, there are ways 1138 * libraries. A library that is only used as a source is never
1217 * that are open to regular files that are not available to 1139 * considered out-of-date by itself. This does not preclude the
1218 * libraries. A library that is only used as a source is never 1140 * library's modification time from making its parent be out-of-date.
1219 * considered out-of-date by itself. This does not preclude the 1141 * A library will be considered out-of-date for any of these reasons,
1220 * library's modification time from making its parent be out-of-date. 1142 * given that it is a target on a dependency line somewhere:
1221 * A library will be considered out-of-date for any of these reasons, 1143 *
1222 * given that it is a target on a dependency line somewhere: 1144 * Its modification time is less than that of one of its sources
1223 * Its modification time is less than that of one of its 1145 * (gn->mtime < gn->cmgn->mtime).
1224 * sources (gn->mtime < gn->cmgn->mtime). 1146 *
1225 * Its modification time is greater than the time at which the 1147 * Its modification time is greater than the time at which the make
1226 * make began (i.e. it's been modified in the course 1148 * began (i.e. it's been modified in the course of the make, probably
1227 * of the make, probably by archiving). 1149 * by archiving).
1228 * The modification time of one of its sources is greater than 1150 *
1229 * the one of its RANLIBMAG member (i.e. its table of contents 1151 * The modification time of one of its sources is greater than the one
1230 * is out-of-date). We don't compare of the archive time 1152 * of its RANLIBMAG member (i.e. its table of contents is out-of-date).
1231 * vs. TOC time because they can be too close. In my 1153 * We don't compare of the archive time vs. TOC time because they can be
1232 * opinion we should not bother with the TOC at all since 1154 * too close. In my opinion we should not bother with the TOC at all
1233 * this is used by 'ar' rules that affect the data contents 1155 * since this is used by 'ar' rules that affect the data contents of the
1234 * of the archive, not by ranlib rules, which affect the 1156 * archive, not by ranlib rules, which affect the TOC.
1235 * TOC. 
1236 * 1157 *
1237 * Input: 1158 * Input:
1238 * gn The library's graph node 1159 * gn The library's graph node
1239 * 1160 *
1240 * Results: 1161 * Results:
1241 * TRUE if the library is out-of-date. FALSE otherwise. 1162 * TRUE if the library is out-of-date. FALSE otherwise.
1242 * 
1243 * Side Effects: 
1244 * The library will be hashed if it hasn't been already. 
1245 * 
1246 *----------------------------------------------------------------------- 
1247 */ 1163 */
1248Boolean 1164Boolean
1249Arch_LibOODate(GNode *gn) 1165Arch_LibOODate(GNode *gn)
1250{ 1166{
1251 Boolean oodate; 1167 Boolean oodate;
1252 1168
1253 if (gn->type & OP_PHONY) { 1169 if (gn->type & OP_PHONY) {
1254 oodate = TRUE; 1170 oodate = TRUE;
1255 } else if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) { 1171 } else if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) {
1256 oodate = FALSE; 1172 oodate = FALSE;
1257 } else if ((!Lst_IsEmpty(gn->children) && gn->cmgn == NULL) || 1173 } else if ((!Lst_IsEmpty(gn->children) && gn->cmgn == NULL) ||
1258 (gn->mtime > now) || 1174 (gn->mtime > now) ||
1259 (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime)) { 1175 (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime)) {
1260 oodate = TRUE; 1176 oodate = TRUE;
1261 } else { 1177 } else {
1262#ifdef RANLIBMAG 1178#ifdef RANLIBMAG
1263 struct ar_hdr *arhPtr; /* Header for __.SYMDEF */ 1179 struct ar_hdr *arhPtr; /* Header for __.SYMDEF */
1264 int modTimeTOC; /* The table-of-contents's mod time */ 1180 int modTimeTOC; /* The table-of-contents's mod time */
1265 1181
1266 arhPtr = ArchStatMember(gn->path, RANLIBMAG, FALSE); 1182 arhPtr = ArchStatMember(gn->path, RANLIBMAG, FALSE);
1267 1183
1268 if (arhPtr != NULL) { 1184 if (arhPtr != NULL) {
1269 modTimeTOC = (int)strtol(arhPtr->ar_date, NULL, 10); 1185 modTimeTOC = (int)strtol(arhPtr->ar_date, NULL, 10);
1270 1186
1271 if (DEBUG(ARCH) || DEBUG(MAKE)) { 1187 if (DEBUG(ARCH) || DEBUG(MAKE)) {
1272 fprintf(debug_file, "%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); 1188 fprintf(debug_file, "%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC));
1273 } 1189 }
1274 oodate = (gn->cmgn == NULL || gn->cmgn->mtime > modTimeTOC); 1190 oodate = (gn->cmgn == NULL || gn->cmgn->mtime > modTimeTOC);
1275 } else { 1191 } else {
1276 /* 1192 /*
1277 * A library w/o a table of contents is out-of-date 1193 * A library w/o a table of contents is out-of-date
1278 */ 1194 */
1279 if (DEBUG(ARCH) || DEBUG(MAKE)) { 1195 if (DEBUG(ARCH) || DEBUG(MAKE)) {
1280 fprintf(debug_file, "No t.o.c...."); 1196 fprintf(debug_file, "No t.o.c....");
1281 } 1197 }
1282 oodate = TRUE; 1198 oodate = TRUE;
1283 } 1199 }
1284#else 1200#else
1285 oodate = FALSE; 1201 oodate = FALSE;
1286#endif 1202#endif
1287 } 1203 }
1288 return oodate; 1204 return oodate;
1289} 1205}
1290 1206
1291/* Initialize things for this module. */ 1207/* Initialize things for this module. */
1292void 1208void
1293Arch_Init(void) 1209Arch_Init(void)
1294{ 1210{
1295 archives = Lst_Init(); 1211 archives = Lst_Init();
1296} 1212}
1297 1213
1298/* Clean up things for this module. */ 1214/* Clean up things for this module. */
1299void 1215void
1300Arch_End(void) 1216Arch_End(void)
1301{ 1217{
1302#ifdef CLEANUP 1218#ifdef CLEANUP
1303 Lst_Destroy(archives, ArchFree); 1219 Lst_Destroy(archives, ArchFree);
1304#endif 1220#endif
1305} 1221}
1306 1222
1307/*- 1223Boolean
1308 *----------------------------------------------------------------------- 
1309 * Arch_IsLib -- 
1310 * Check if the node is a library 
1311 * 
1312 * Results: 
1313 * True or False. 
1314 * 
1315 * Side Effects: 
1316 * None. 
1317 * 
1318 *----------------------------------------------------------------------- 
1319 */ 
1320int 
1321Arch_IsLib(GNode *gn) 1224Arch_IsLib(GNode *gn)
1322{ 1225{
1323 static const char armag[] = "!<arch>\n"; 1226 static const char armag[] = "!<arch>\n";
1324 char buf[sizeof(armag)-1]; 1227 char buf[sizeof armag - 1];
1325 int fd; 1228 int fd;
1326 1229
1327 if ((fd = open(gn->path, O_RDONLY)) == -1) 1230 if ((fd = open(gn->path, O_RDONLY)) == -1)
1328 return FALSE; 1231 return FALSE;
1329 1232
1330 if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { 1233 if (read(fd, buf, sizeof buf) != sizeof buf) {
1331 (void)close(fd); 1234 (void)close(fd);
1332 return FALSE; 1235 return FALSE;
1333 } 1236 }
1334 1237
1335 (void)close(fd); 1238 (void)close(fd);
1336 1239
1337 return memcmp(buf, armag, sizeof(buf)) == 0; 1240 return memcmp(buf, armag, sizeof buf) == 0;
1338} 1241}