Lst_AtEnd(nodeLst, (ClientData)gn);
Lst_AtEnd(nodeLst, gn);
Arch_ParseArchive (linePtr, nodeLst, ctxt)    char	    **linePtr;      /* Pointer to start of specification */    Lst	    	    nodeLst;   	    /* Lst on which to place the nodes */    GNode   	    *ctxt;  	    /* Context in which to expand variables */{    register char   *cp;	    /* Pointer into line */    GNode	    *gn;     	    /* New node */    char	    *libName;  	    /* Library-part of specification */    char	    *memName;  	    /* Member-part of specification */    char	    nameBuf[MAKE_BSIZE]; /* temporary place for node name */    char	    saveChar;  	    /* Ending delimiter of member-name */    Boolean 	    subLibName;	    /* TRUE if libName should have/had				     * variable substitution performed on it */    libName = *linePtr;    subLibName = FALSE;    for (cp = libName; *cp != '(' && *cp != '\0'; cp++) {	if (*cp == '$') {	    /*	     * Variable spec, so call the Var module to parse the puppy	     * so we can safely advance beyond it...	     */	    size_t 	length;	    Boolean	freeIt;	    char	*result;	    result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt);	    if (result == var_Error) {		return(FAILURE);	    } else {		subLibName = TRUE;	    }	    if (freeIt) {		free(result);	    }	    cp += length-1;	}    }    *cp++ = '\0';    if (subLibName) {	libName = Var_Subst(libName, ctxt, TRUE);    }    for (;;) {	/*	 * First skip to the start of the member's name, mark that	 * place and skip to the end of it (either white-space or	 * a close paren).	 */	Boolean	doSubst = FALSE; /* TRUE if need to substitute in memName */	while (*cp != '\0' && *cp != ')' && isspace (*cp)) {	    cp++;	}	memName = cp;	while (*cp != '\0' && *cp != ')' && !isspace (*cp)) {	    if (*cp == '$') {		/*		 * Variable spec, so call the Var module to parse the puppy		 * so we can safely advance beyond it...		 */		size_t 	length;		Boolean	freeIt;		char	*result;		result=Var_Parse(cp, ctxt, TRUE, &length, &freeIt);		if (result == var_Error) {		    return(FAILURE);		} else {		    doSubst = TRUE;		}		if (freeIt) {		    free(result);		}		cp += length;	    } else {		cp++;	    }	}	/*	 * If the specification ends without a closing parenthesis,	 * chances are there's something wrong (like a missing backslash),	 * so it's better to return failure than allow such things to happen	 */	if (*cp == '\0') {	    printf("No closing parenthesis in archive specification\n");	    return (FAILURE);	}	/*	 * If we didn't move anywhere, we must be done	 */	if (cp == memName) {	    break;	}	saveChar = *cp;	*cp = '\0';	/*	 * XXX: This should be taken care of intelligently by	 * SuffExpandChildren, both for the archive and the member portions.	 */	/*	 * If member contains variables, try and substitute for them.	 * This will slow down archive specs with dynamic sources, of course,	 * since we'll be (non-)substituting them three times, but them's	 * the breaks -- we need to do this since SuffExpandChildren calls	 * us, otherwise we could assume the thing would be taken care of	 * later.	 */	if (doSubst) {	    char    *buf;	    char    *sacrifice;	    char    *oldMemName = memName;	    memName = Var_Subst(memName, ctxt, TRUE);	    /*	     * Now form an archive spec and recurse to deal with nested	     * variables and multi-word variable values.... The results	     * are just placed at the end of the nodeLst we're returning.	     */	    buf = sacrifice = emalloc(strlen(memName)+strlen(libName)+3);	    sprintf(buf, "%s(%s)", libName, memName);	    if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) {		/*		 * Must contain dynamic sources, so we can't deal with it now.		 * Just create an ARCHV node for the thing and let		 * SuffExpandChildren handle it...		 */		gn = Targ_FindNode(buf, TARG_CREATE);		if (gn == NULL) {		    free(buf);		    return(FAILURE);		} else {		    gn->type |= OP_ARCHV;		    Lst_AtEnd(nodeLst, (ClientData)gn);		}	    } else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) {		/*		 * Error in nested call -- free buffer and return FAILURE		 * ourselves.		 */		free(buf);		return(FAILURE);	    }	    /*	     * Free buffer and continue with our work.	     */	    free(buf);	} else if (Dir_HasWildcards(memName)) {	    Lst	  members = Lst_Init();	    char  *member;	    Dir_Expand(memName, dirSearchPath, members);	    while ((member = (char *)Lst_DeQueue(members)) != NULL) {		sprintf(nameBuf, "%s(%s)", libName, member);		free(member);		gn = Targ_FindNode (nameBuf, TARG_CREATE);		if (gn == NULL) {		    return (FAILURE);		} else {		    /*		     * We've found the node, but have to make sure the rest of		     * the world knows it's an archive member, without having		     * to constantly check for parentheses, so we type the		     * thing with the OP_ARCHV bit before we place it on the		     * end of the provided list.		     */		    gn->type |= OP_ARCHV;		    Lst_AtEnd(nodeLst, (ClientData)gn);		}	    }	    Lst_Destroy(members, NOFREE);	} else {	    sprintf(nameBuf, "%s(%s)", libName, memName);	    gn = Targ_FindNode (nameBuf, TARG_CREATE);	    if (gn == NULL) {		return (FAILURE);	    } else {		/*		 * We've found the node, but have to make sure the rest of the		 * world knows it's an archive member, without having to		 * constantly check for parentheses, so we type the thing with		 * the OP_ARCHV bit before we place it on the end of the		 * provided list.		 */		gn->type |= OP_ARCHV;		Lst_AtEnd(nodeLst, (ClientData)gn);	    }	}	if (doSubst) {	    free(memName);	}	*cp = saveChar;    }    /*     * If substituted libName, free it now, since we need it no longer.     */    if (subLibName) {	free(libName);    }    /*     * We promised the pointer would be set up at the next non-space, so     * we must advance cp there before setting *linePtr... (note that on     * entrance to the loop, cp is guaranteed to point at a ')')     */    do {	cp++;    } while (*cp != '\0' && isspace (*cp));    *linePtr = cp;    return (SUCCESS);}