| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: arch.c,v 1.97 2020/08/26 22:55:46 rillig Exp $ */ | | 1 | /* $NetBSD: arch.c,v 1.98 2020/08/27 06:13:53 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. |
| @@ -59,34 +59,34 @@ | | | @@ -59,34 +59,34 @@ |
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 |
72 | static char rcsid[] = "$NetBSD: arch.c,v 1.97 2020/08/26 22:55:46 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: arch.c,v 1.98 2020/08/27 06:13:53 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 |
77 | static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; | | 77 | static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; |
78 | #else | | 78 | #else |
79 | __RCSID("$NetBSD: arch.c,v 1.97 2020/08/26 22:55:46 rillig Exp $"); | | 79 | __RCSID("$NetBSD: arch.c,v 1.98 2020/08/27 06:13:53 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. |
| @@ -215,36 +215,36 @@ ArchFree(void *ap) | | | @@ -215,36 +215,36 @@ ArchFree(void *ap) |
215 | /*- | | 215 | /*- |
216 | *----------------------------------------------------------------------- | | 216 | *----------------------------------------------------------------------- |
217 | * Arch_ParseArchive -- | | 217 | * Arch_ParseArchive -- |
218 | * Parse the archive specification in the given line and find/create | | 218 | * Parse the archive specification in the given line and find/create |
219 | * the nodes for the specified archive members, placing their nodes | | 219 | * the nodes for the specified archive members, placing their nodes |
220 | * on the given list. | | 220 | * on the given list. |
221 | * | | 221 | * |
222 | * Input: | | 222 | * Input: |
223 | * linePtr Pointer to start of specification | | 223 | * linePtr Pointer to start of specification |
224 | * nodeLst Lst on which to place the nodes | | 224 | * nodeLst Lst on which to place the nodes |
225 | * ctxt Context in which to expand variables | | 225 | * ctxt Context in which to expand variables |
226 | * | | 226 | * |
227 | * Results: | | 227 | * Results: |
228 | * SUCCESS if it was a valid specification. The linePtr is updated | | 228 | * TRUE if it was a valid specification. The linePtr is updated |
229 | * to point to the first non-space after the archive spec. The | | 229 | * to point to the first non-space after the archive spec. The |
230 | * nodes for the members are placed on the given list. | | 230 | * nodes for the members are placed on the given list. |
231 | * | | 231 | * |
232 | * Side Effects: | | 232 | * Side Effects: |
233 | * Some nodes may be created. The given list is extended. | | 233 | * Some nodes may be created. The given list is extended. |
234 | * | | 234 | * |
235 | *----------------------------------------------------------------------- | | 235 | *----------------------------------------------------------------------- |
236 | */ | | 236 | */ |
237 | ReturnStatus | | 237 | Boolean |
238 | Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) | | 238 | Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) |
239 | { | | 239 | { |
240 | char *cp; /* Pointer into line */ | | 240 | char *cp; /* Pointer into line */ |
241 | GNode *gn; /* New node */ | | 241 | GNode *gn; /* New node */ |
242 | char *libName; /* Library-part of specification */ | | 242 | char *libName; /* Library-part of specification */ |
243 | char *memName; /* Member-part of specification */ | | 243 | char *memName; /* Member-part of specification */ |
244 | char saveChar; /* Ending delimiter of member-name */ | | 244 | char saveChar; /* Ending delimiter of member-name */ |
245 | Boolean subLibName; /* TRUE if libName should have/had | | 245 | Boolean subLibName; /* TRUE if libName should have/had |
246 | * variable substitution performed on it */ | | 246 | * variable substitution performed on it */ |
247 | | | 247 | |
248 | libName = *linePtr; | | 248 | libName = *linePtr; |
249 | | | 249 | |
250 | subLibName = FALSE; | | 250 | subLibName = FALSE; |
| @@ -254,27 +254,27 @@ Arch_ParseArchive(char **linePtr, Lst no | | | @@ -254,27 +254,27 @@ Arch_ParseArchive(char **linePtr, Lst no |
254 | /* | | 254 | /* |
255 | * Variable spec, so call the Var module to parse the puppy | | 255 | * Variable spec, so call the Var module to parse the puppy |
256 | * so we can safely advance beyond it... | | 256 | * so we can safely advance beyond it... |
257 | */ | | 257 | */ |
258 | int length; | | 258 | int length; |
259 | void *freeIt; | | 259 | void *freeIt; |
260 | const char *result; | | 260 | const char *result; |
261 | | | 261 | |
262 | result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, | | 262 | result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, |
263 | &length, &freeIt); | | 263 | &length, &freeIt); |
264 | free(freeIt); | | 264 | free(freeIt); |
265 | | | 265 | |
266 | if (result == var_Error) { | | 266 | if (result == var_Error) { |
267 | return FAILURE; | | 267 | return FALSE; |
268 | } else { | | 268 | } else { |
269 | subLibName = TRUE; | | 269 | subLibName = TRUE; |
270 | } | | 270 | } |
271 | | | 271 | |
272 | cp += length-1; | | 272 | cp += length-1; |
273 | } | | 273 | } |
274 | } | | 274 | } |
275 | | | 275 | |
276 | *cp++ = '\0'; | | 276 | *cp++ = '\0'; |
277 | if (subLibName) { | | 277 | if (subLibName) { |
278 | libName = Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES); | | 278 | libName = Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES); |
279 | } | | 279 | } |
280 | | | 280 | |
| @@ -296,45 +296,45 @@ Arch_ParseArchive(char **linePtr, Lst no | | | @@ -296,45 +296,45 @@ Arch_ParseArchive(char **linePtr, Lst no |
296 | /* | | 296 | /* |
297 | * Variable spec, so call the Var module to parse the puppy | | 297 | * Variable spec, so call the Var module to parse the puppy |
298 | * so we can safely advance beyond it... | | 298 | * so we can safely advance beyond it... |
299 | */ | | 299 | */ |
300 | int length; | | 300 | int length; |
301 | void *freeIt; | | 301 | void *freeIt; |
302 | const char *result; | | 302 | const char *result; |
303 | | | 303 | |
304 | result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, | | 304 | result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, |
305 | &length, &freeIt); | | 305 | &length, &freeIt); |
306 | free(freeIt); | | 306 | free(freeIt); |
307 | | | 307 | |
308 | if (result == var_Error) { | | 308 | if (result == var_Error) { |
309 | return FAILURE; | | 309 | return FALSE; |
310 | } else { | | 310 | } else { |
311 | doSubst = TRUE; | | 311 | doSubst = TRUE; |
312 | } | | 312 | } |
313 | | | 313 | |
314 | cp += length; | | 314 | cp += length; |
315 | } else { | | 315 | } else { |
316 | cp++; | | 316 | cp++; |
317 | } | | 317 | } |
318 | } | | 318 | } |
319 | | | 319 | |
320 | /* | | 320 | /* |
321 | * If the specification ends without a closing parenthesis, | | 321 | * If the specification ends without a closing parenthesis, |
322 | * chances are there's something wrong (like a missing backslash), | | 322 | * chances are there's something wrong (like a missing backslash), |
323 | * so it's better to return failure than allow such things to happen | | 323 | * so it's better to return failure than allow such things to happen |
324 | */ | | 324 | */ |
325 | if (*cp == '\0') { | | 325 | if (*cp == '\0') { |
326 | printf("No closing parenthesis in archive specification\n"); | | 326 | printf("No closing parenthesis in archive specification\n"); |
327 | return FAILURE; | | 327 | return FALSE; |
328 | } | | 328 | } |
329 | | | 329 | |
330 | /* | | 330 | /* |
331 | * If we didn't move anywhere, we must be done | | 331 | * If we didn't move anywhere, we must be done |
332 | */ | | 332 | */ |
333 | if (cp == memName) { | | 333 | if (cp == memName) { |
334 | break; | | 334 | break; |
335 | } | | 335 | } |
336 | | | 336 | |
337 | saveChar = *cp; | | 337 | saveChar = *cp; |
338 | *cp = '\0'; | | 338 | *cp = '\0'; |
339 | | | 339 | |
340 | /* | | 340 | /* |
| @@ -363,90 +363,90 @@ Arch_ParseArchive(char **linePtr, Lst no | | | @@ -363,90 +363,90 @@ Arch_ParseArchive(char **linePtr, Lst no |
363 | */ | | 363 | */ |
364 | buf = sacrifice = str_concat4(libName, "(", memName, ")"); | | 364 | buf = sacrifice = str_concat4(libName, "(", memName, ")"); |
365 | | | 365 | |
366 | if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { | | 366 | if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { |
367 | /* | | 367 | /* |
368 | * Must contain dynamic sources, so we can't deal with it now. | | 368 | * Must contain dynamic sources, so we can't deal with it now. |
369 | * Just create an ARCHV node for the thing and let | | 369 | * Just create an ARCHV node for the thing and let |
370 | * SuffExpandChildren handle it... | | 370 | * SuffExpandChildren handle it... |
371 | */ | | 371 | */ |
372 | gn = Targ_FindNode(buf, TARG_CREATE); | | 372 | gn = Targ_FindNode(buf, TARG_CREATE); |
373 | | | 373 | |
374 | if (gn == NULL) { | | 374 | if (gn == NULL) { |
375 | free(buf); | | 375 | free(buf); |
376 | return FAILURE; | | 376 | return FALSE; |
377 | } else { | | 377 | } else { |
378 | gn->type |= OP_ARCHV; | | 378 | gn->type |= OP_ARCHV; |
379 | Lst_AppendS(nodeLst, gn); | | 379 | Lst_AppendS(nodeLst, gn); |
380 | } | | 380 | } |
381 | } else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) { | | 381 | } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) { |
382 | /* | | 382 | /* |
383 | * Error in nested call -- free buffer and return FAILURE | | 383 | * Error in nested call -- free buffer and return FAILURE |
384 | * ourselves. | | 384 | * ourselves. |
385 | */ | | 385 | */ |
386 | free(buf); | | 386 | free(buf); |
387 | return FAILURE; | | 387 | return FALSE; |
388 | } | | 388 | } |
389 | /* | | 389 | /* |
390 | * Free buffer and continue with our work. | | 390 | * Free buffer and continue with our work. |
391 | */ | | 391 | */ |
392 | free(buf); | | 392 | free(buf); |
393 | } else if (Dir_HasWildcards(memName)) { | | 393 | } else if (Dir_HasWildcards(memName)) { |
394 | Lst members = Lst_Init(); | | 394 | Lst members = Lst_Init(); |
395 | Buffer nameBuf; | | 395 | Buffer nameBuf; |
396 | | | 396 | |
397 | Buf_Init(&nameBuf, 0); | | 397 | Buf_Init(&nameBuf, 0); |
398 | Dir_Expand(memName, dirSearchPath, members); | | 398 | Dir_Expand(memName, dirSearchPath, members); |
399 | while (!Lst_IsEmpty(members)) { | | 399 | while (!Lst_IsEmpty(members)) { |
400 | char *member = Lst_DequeueS(members); | | 400 | char *member = Lst_DequeueS(members); |
401 | | | 401 | |
402 | Buf_Empty(&nameBuf); | | 402 | Buf_Empty(&nameBuf); |
403 | Buf_AddStr(&nameBuf, libName); | | 403 | Buf_AddStr(&nameBuf, libName); |
404 | Buf_AddStr(&nameBuf, "("); | | 404 | Buf_AddStr(&nameBuf, "("); |
405 | Buf_AddStr(&nameBuf, member); | | 405 | Buf_AddStr(&nameBuf, member); |
406 | Buf_AddStr(&nameBuf, ")"); | | 406 | Buf_AddStr(&nameBuf, ")"); |
407 | free(member); | | 407 | free(member); |
408 | | | 408 | |
409 | gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); | | 409 | gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); |
410 | if (gn == NULL) { | | 410 | if (gn == NULL) { |
411 | Buf_Destroy(&nameBuf, TRUE); | | 411 | Buf_Destroy(&nameBuf, TRUE); |
412 | return FAILURE; | | 412 | return FALSE; |
413 | } else { | | 413 | } else { |
414 | /* | | 414 | /* |
415 | * We've found the node, but have to make sure the rest of | | 415 | * We've found the node, but have to make sure the rest of |
416 | * the world knows it's an archive member, without having | | 416 | * the world knows it's an archive member, without having |
417 | * to constantly check for parentheses, so we type the | | 417 | * to constantly check for parentheses, so we type the |
418 | * thing with the OP_ARCHV bit before we place it on the | | 418 | * thing with the OP_ARCHV bit before we place it on the |
419 | * end of the provided list. | | 419 | * end of the provided list. |
420 | */ | | 420 | */ |
421 | gn->type |= OP_ARCHV; | | 421 | gn->type |= OP_ARCHV; |
422 | Lst_AppendS(nodeLst, gn); | | 422 | Lst_AppendS(nodeLst, gn); |
423 | } | | 423 | } |
424 | } | | 424 | } |
425 | Lst_FreeS(members); | | 425 | Lst_FreeS(members); |
426 | Buf_Destroy(&nameBuf, TRUE); | | 426 | Buf_Destroy(&nameBuf, TRUE); |
427 | } else { | | 427 | } else { |
428 | Buffer nameBuf; | | 428 | Buffer nameBuf; |
429 | | | 429 | |
430 | Buf_Init(&nameBuf, 0); | | 430 | Buf_Init(&nameBuf, 0); |
431 | Buf_AddStr(&nameBuf, libName); | | 431 | Buf_AddStr(&nameBuf, libName); |
432 | Buf_AddStr(&nameBuf, "("); | | 432 | Buf_AddStr(&nameBuf, "("); |
433 | Buf_AddStr(&nameBuf, memName); | | 433 | Buf_AddStr(&nameBuf, memName); |
434 | Buf_AddStr(&nameBuf, ")"); | | 434 | Buf_AddStr(&nameBuf, ")"); |
435 | | | 435 | |
436 | gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); | | 436 | gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); |
437 | Buf_Destroy(&nameBuf, TRUE); | | 437 | Buf_Destroy(&nameBuf, TRUE); |
438 | if (gn == NULL) { | | 438 | if (gn == NULL) { |
439 | return FAILURE; | | 439 | return FALSE; |
440 | } else { | | 440 | } else { |
441 | /* | | 441 | /* |
442 | * We've found the node, but have to make sure the rest of the | | 442 | * 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 | | 443 | * world knows it's an archive member, without having to |
444 | * constantly check for parentheses, so we type the thing with | | 444 | * constantly check for parentheses, so we type the thing with |
445 | * the OP_ARCHV bit before we place it on the end of the | | 445 | * the OP_ARCHV bit before we place it on the end of the |
446 | * provided list. | | 446 | * provided list. |
447 | */ | | 447 | */ |
448 | gn->type |= OP_ARCHV; | | 448 | gn->type |= OP_ARCHV; |
449 | Lst_AppendS(nodeLst, gn); | | 449 | Lst_AppendS(nodeLst, gn); |
450 | } | | 450 | } |
451 | } | | 451 | } |
452 | if (doSubst) { | | 452 | if (doSubst) { |
| @@ -463,27 +463,27 @@ Arch_ParseArchive(char **linePtr, Lst no | | | @@ -463,27 +463,27 @@ Arch_ParseArchive(char **linePtr, Lst no |
463 | free(libName); | | 463 | free(libName); |
464 | } | | 464 | } |
465 | | | 465 | |
466 | /* | | 466 | /* |
467 | * We promised the pointer would be set up at the next non-space, so | | 467 | * 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 | | 468 | * we must advance cp there before setting *linePtr... (note that on |
469 | * entrance to the loop, cp is guaranteed to point at a ')') | | 469 | * entrance to the loop, cp is guaranteed to point at a ')') |
470 | */ | | 470 | */ |
471 | do { | | 471 | do { |
472 | cp++; | | 472 | cp++; |
473 | } while (*cp != '\0' && isspace ((unsigned char)*cp)); | | 473 | } while (*cp != '\0' && isspace ((unsigned char)*cp)); |
474 | | | 474 | |
475 | *linePtr = cp; | | 475 | *linePtr = cp; |
476 | return SUCCESS; | | 476 | return TRUE; |
477 | } | | 477 | } |
478 | | | 478 | |
479 | /*- | | 479 | /*- |
480 | *----------------------------------------------------------------------- | | 480 | *----------------------------------------------------------------------- |
481 | * ArchFindArchive -- | | 481 | * ArchFindArchive -- |
482 | * See if the given archive is the one we are looking for. Called | | 482 | * See if the given archive is the one we are looking for. Called |
483 | * From ArchStatMember and ArchFindMember via Lst_Find. | | 483 | * From ArchStatMember and ArchFindMember via Lst_Find. |
484 | * | | 484 | * |
485 | * Input: | | 485 | * Input: |
486 | * ar Current list element | | 486 | * ar Current list element |
487 | * archName Name we want | | 487 | * archName Name we want |
488 | * | | 488 | * |
489 | * Results: | | 489 | * Results: |