diff options
Diffstat (limited to 'dmake/stat.c')
-rw-r--r-- | dmake/stat.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/dmake/stat.c b/dmake/stat.c new file mode 100644 index 000000000000..4bd4db810af1 --- /dev/null +++ b/dmake/stat.c @@ -0,0 +1,278 @@ +/* RCS $Id: stat.c,v 1.3 2007-10-15 15:41:38 ihi Exp $ +-- +-- SYNOPSIS +-- Bind a target name to a file. +-- +-- DESCRIPTION +-- This file contains the code to go and stat a target. The stat rules +-- follow a predefined order defined in the comment for Stat_target. +-- +-- AUTHOR +-- Dennis Vadura, dvadura@dmake.wticorp.com +-- +-- WWW +-- http://dmake.wticorp.com/ +-- +-- COPYRIGHT +-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved. +-- +-- This program is NOT free software; you can redistribute it and/or +-- modify it under the terms of the Software License Agreement Provided +-- in the file <distribution-root>/readme/license.txt. +-- +-- LOG +-- Use cvs log to obtain detailed change logs. +*/ + +#include "extern.h" + + +static int _check_dir_list ANSI((CELLPTR, CELLPTR, int, int)); + +#ifdef DBUG + /* Just a little ditty for debugging this thing */ + static time_t + _do_stat( name, lib, sym, force ) + char *name; + char *lib; + char **sym; + int force; + { + time_t res; + DB_ENTER( "_do_stat" ); + + res = Do_stat(name, lib, sym, force); + DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) ); + + DB_RETURN( res ); + } +#define DO_STAT(A,B,C,D) _do_stat(A,B,C,D) +#else +#define DO_STAT(A,B,C,D) Do_stat(A,B,C,D) +#endif + +static char *_first; /* If set this variable saves the first pathname that was + * used to stat the target in, if subsequently a match is + * found it is overridden by the matched path name. */ + +PUBLIC void +Stat_target( cp, setfname, force )/* +==================================== + Stat a target. When doing so follow the following rules, suppose + that cp->CE_NAME points at a target called fred.o: + (See also man page: BINDING TARGETS) + + 0. If A_SYMBOL attribute set look into the library + then do the steps 1 thru 4 on the resulting name. + 1. Try path's obtained by prepending any dirs found as + prerequisites for .SOURCE.o. + 2. If not found, do same as 2 but use .SOURCE + The predefined '.SOURCE : .NULL' targets takes care + of local/absolute paths. + 3. If not found and .LIBRARYM attribute for the target is + set then look for it in the corresponding library. + 4. If found in step 0 thru 3, then ce_fname points at + file name associate with target, else ce_fname points + at a file name built by the first .SOURCE* dir that + applied. + If setfname is != 0 this tells _check_dir_list() to set the static + _first variable. setfname also controls the use of _first. + If it is -1 ce_fname (the file name associated with target) is only + set if a matching file was found and statted, if it is 1 ce_fname + is set to _first even if target doesn't exist yet. + + If force is TRUE really stat the target. Do not use the directory + cache but update the files entry if it's enabled. */ + +CELLPTR cp; +int setfname; +int force; +{ + register HASHPTR hp; + static HASHPTR srchp = NIL(HASH); + char *name; + char *tmp; + int res = 0; + + DB_ENTER( "Stat_target" ); + + name = cp->CE_NAME; + DB_PRINT( "stat", ("called on [%s]", name) ); + + if( srchp == NIL(HASH) ) srchp = Get_name(".SOURCE",Defs,FALSE); + + /* Look for a symbol of the form lib((symbol)) the name of the symbol + * as entered in the hash table is (symbol) so pull out symbol and try + * to find it's module. If successful DO_STAT will return the module + * as well as the archive member name (pointed at by tmp). We then + * replace the symbol name with the archive member name so that we + * have the proper name for any future refrences. */ + + if( cp->ce_attr & A_SYMBOL ) { + DB_PRINT( "stat", ("Binding lib symbol [%s]", name) ); + + cp->ce_time = DO_STAT( name, cp->ce_lib, &tmp, force ); + + if( cp->ce_time != (time_t) 0L ) { + /* stat the new member name below note tmp must point at a string + * returned by MALLOC... ie. the Do_stat code should use DmStrDup */ + + if( Verbose & V_MAKE ) + printf( "%s: Mapped ((%s)) to %s(%s)\n", Pname, + name, cp->ce_lib, tmp ); + + FREE( name ); + name = cp->CE_NAME = tmp; + cp->ce_attr &= ~(A_FFNAME | A_SYMBOL); + } + else + { DB_VOID_RETURN; } + } + + _first = NIL(char); + tmp = DmStrJoin( ".SOURCE", Get_suffix(name), -1, FALSE); + + /* Check .SOURCE.xxx target */ + if( (hp = Get_name(tmp, Defs, FALSE)) != NIL(HASH) ) + res = _check_dir_list( cp, hp->CP_OWNR, setfname, force ); + + /* Check just .SOURCE */ + if( !res && (srchp != NIL(HASH)) ) + res = _check_dir_list( cp, srchp->CP_OWNR, setfname, force ); + + /* If libmember and we haven't found it check the library */ + if( !res && (cp->ce_attr & A_LIBRARYM) ) { + cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *), force); + + if( !cp->ce_time && Tmd && *Tmd && cp->ce_lib ) { + char *tmplib; + tmplib=DmStrDup(Build_path(Tmd,cp->ce_lib)); + + if ((cp->ce_time = DO_STAT(name, tmplib, NIL(char *),force)) != (time_t)0L){ + cp->ce_lib=DmStrDup(tmplib); + } + } + + if( Verbose & V_MAKE ) + printf( "%s: Checking library '%s' for member [%s], time %ld\n", + Pname, cp->ce_lib, name, cp->ce_time ); + } + + FREE( tmp ); + + if( setfname == 1 || (setfname == -1 && cp->ce_time != (time_t)0L) ) { + int setlib = (cp->ce_lib == cp->ce_fname); + + if( (cp->ce_attr & A_FFNAME) && (cp->ce_fname != NIL(char)) ) + FREE( cp->ce_fname ); + + if( _first != NIL(char) ) { + cp->ce_fname = _first; + cp->ce_attr |= A_FFNAME; + } + else { + cp->ce_fname = cp->CE_NAME; + cp->ce_attr &= ~A_FFNAME; + } + + if ( setlib ) cp->ce_lib = cp->ce_fname; + } + else if( _first ) + FREE( _first ); + + /* set it as stated only if successful, this way, we shall try again + * later. */ + if( cp->ce_time != (time_t)0L ) { + cp->ce_flag |= F_STAT; + + /* If it is a whatif this changed scenario then return the current + * time, but do so only if the stat was successful. */ + if ( (cp->ce_attr & A_WHATIF) && !(cp->ce_flag & F_MADE) ) { + cp->ce_time = Do_time(); + } + } + + DB_VOID_RETURN; +} + + +static int +_check_dir_list( cp, sp, setfname, force )/* +============================================ + Check the list of dir's given by the prerequisite list of sp, for a + file pointed at by cp. Returns 0 if path not bound, else returns + 1 and replaces old name for cell with new cell name. */ + +CELLPTR cp; +CELLPTR sp; +int setfname; +int force; +{ + /* FIXME: BCC 5.0 BUG??? If lp is assigned to a register variable then + * BCC 5.0 corrupts a field of the member structure when DO_STAT + * calls the native win95 stat system call. Blech!!! + * + * Making this a static variable forces it out of a register and + * seems to avoid the problem. */ + static LINKPTR lp; + char *dir; + char *path; + char *name; + int res = 0; + int fset = 0; + + DB_ENTER( "_check_dir_list" ); + DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) ); + + if( sp->ce_prq != NIL(LINK) ) /* check prerequisites if any */ + { + /* Use the real name instead of basename, this prevents silly + * loops in inference code, and is consistent with man page */ + name = cp->CE_NAME; + + /* Here we loop through each directory on the list, and try to stat + * the target. We always save the first pathname we try to stat in + * _first. If we subsequently get a match we then replace the value of + * _first by the matched path name. */ + + for( lp=sp->CE_PRQ; lp != NIL(LINK) && !res; lp=lp->cl_next ) { + int nodup = 0; + dir = lp->cl_prq->CE_NAME; + + if( strchr( dir, '$' ) ) dir = Expand(dir); + if( strcmp( dir, ".NULL" ) == 0 ) { + nodup = 1; + path = cp->CE_NAME; + } else { + path = DmStrDup(Build_path(dir,name)); + } + + res = ((cp->ce_time=DO_STAT(path,NIL(char),NIL(char *),force))!=(time_t)0L); + + /* Have to use DmStrDup to set _first since Build_path, builds it's + * path names inside a static buffer. */ + if( setfname ) + if( (_first == NIL(char) && !fset) || res ) { + if( _first != NIL(char) ) FREE( _first ); + if (nodup) + _first = NIL(char); + else { + _first = path; + path = NIL(char); + } + fset = 1; + } + + DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) ); + if( dir != lp->cl_prq->CE_NAME ) FREE(dir); + if( path && path != cp->CE_NAME ) FREE(path); + } + } + + DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) ); + DB_RETURN( res ); +} + + + + |