1 /* RCS $Id: stat.c,v 1.3 2007-10-15 15:41:38 ihi Exp $
4 -- Bind a target name to a file.
7 -- This file contains the code to go and stat a target. The stat rules
8 -- follow a predefined order defined in the comment for Stat_target.
11 -- Dennis Vadura, dvadura@dmake.wticorp.com
14 -- http://dmake.wticorp.com/
17 -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
19 -- This program is NOT free software; you can redistribute it and/or
20 -- modify it under the terms of the Software License Agreement Provided
21 -- in the file <distribution-root>/readme/license.txt.
24 -- Use cvs log to obtain detailed change logs.
30 static int _check_dir_list
ANSI((CELLPTR
, CELLPTR
, int, int));
33 /* Just a little ditty for debugging this thing */
35 _do_stat( name
, lib
, sym
, force
)
42 DB_ENTER( "_do_stat" );
44 res
= Do_stat(name
, lib
, sym
, force
);
45 DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name
, lib
, sym
, res
) );
49 #define DO_STAT(A,B,C,D) _do_stat(A,B,C,D)
51 #define DO_STAT(A,B,C,D) Do_stat(A,B,C,D)
54 static char *_first
; /* If set this variable saves the first pathname that was
55 * used to stat the target in, if subsequently a match is
56 * found it is overridden by the matched path name. */
59 Stat_target( cp
, setfname
, force
)/*
60 ====================================
61 Stat a target. When doing so follow the following rules, suppose
62 that cp->CE_NAME points at a target called fred.o:
63 (See also man page: BINDING TARGETS)
65 0. If A_SYMBOL attribute set look into the library
66 then do the steps 1 thru 4 on the resulting name.
67 1. Try path's obtained by prepending any dirs found as
68 prerequisites for .SOURCE.o.
69 2. If not found, do same as 2 but use .SOURCE
70 The predefined '.SOURCE : .NULL' targets takes care
71 of local/absolute paths.
72 3. If not found and .LIBRARYM attribute for the target is
73 set then look for it in the corresponding library.
74 4. If found in step 0 thru 3, then ce_fname points at
75 file name associate with target, else ce_fname points
76 at a file name built by the first .SOURCE* dir that
78 If setfname is != 0 this tells _check_dir_list() to set the static
79 _first variable. setfname also controls the use of _first.
80 If it is -1 ce_fname (the file name associated with target) is only
81 set if a matching file was found and statted, if it is 1 ce_fname
82 is set to _first even if target doesn't exist yet.
84 If force is TRUE really stat the target. Do not use the directory
85 cache but update the files entry if it's enabled. */
92 static HASHPTR srchp
= NIL(HASH
);
97 DB_ENTER( "Stat_target" );
100 DB_PRINT( "stat", ("called on [%s]", name
) );
102 if( srchp
== NIL(HASH
) ) srchp
= Get_name(".SOURCE",Defs
,FALSE
);
104 /* Look for a symbol of the form lib((symbol)) the name of the symbol
105 * as entered in the hash table is (symbol) so pull out symbol and try
106 * to find it's module. If successful DO_STAT will return the module
107 * as well as the archive member name (pointed at by tmp). We then
108 * replace the symbol name with the archive member name so that we
109 * have the proper name for any future refrences. */
111 if( cp
->ce_attr
& A_SYMBOL
) {
112 DB_PRINT( "stat", ("Binding lib symbol [%s]", name
) );
114 cp
->ce_time
= DO_STAT( name
, cp
->ce_lib
, &tmp
, force
);
116 if( cp
->ce_time
!= (time_t) 0L ) {
117 /* stat the new member name below note tmp must point at a string
118 * returned by MALLOC... ie. the Do_stat code should use DmStrDup */
120 if( Verbose
& V_MAKE
)
121 printf( "%s: Mapped ((%s)) to %s(%s)\n", Pname
,
122 name
, cp
->ce_lib
, tmp
);
125 name
= cp
->CE_NAME
= tmp
;
126 cp
->ce_attr
&= ~(A_FFNAME
| A_SYMBOL
);
133 tmp
= DmStrJoin( ".SOURCE", Get_suffix(name
), -1, FALSE
);
135 /* Check .SOURCE.xxx target */
136 if( (hp
= Get_name(tmp
, Defs
, FALSE
)) != NIL(HASH
) )
137 res
= _check_dir_list( cp
, hp
->CP_OWNR
, setfname
, force
);
139 /* Check just .SOURCE */
140 if( !res
&& (srchp
!= NIL(HASH
)) )
141 res
= _check_dir_list( cp
, srchp
->CP_OWNR
, setfname
, force
);
143 /* If libmember and we haven't found it check the library */
144 if( !res
&& (cp
->ce_attr
& A_LIBRARYM
) ) {
145 cp
->ce_time
= DO_STAT(name
, cp
->ce_lib
, NIL(char *), force
);
147 if( !cp
->ce_time
&& Tmd
&& *Tmd
&& cp
->ce_lib
) {
149 tmplib
=DmStrDup(Build_path(Tmd
,cp
->ce_lib
));
151 if ((cp
->ce_time
= DO_STAT(name
, tmplib
, NIL(char *),force
)) != (time_t)0L){
152 cp
->ce_lib
=DmStrDup(tmplib
);
156 if( Verbose
& V_MAKE
)
157 printf( "%s: Checking library '%s' for member [%s], time %ld\n",
158 Pname
, cp
->ce_lib
, name
, cp
->ce_time
);
163 if( setfname
== 1 || (setfname
== -1 && cp
->ce_time
!= (time_t)0L) ) {
164 int setlib
= (cp
->ce_lib
== cp
->ce_fname
);
166 if( (cp
->ce_attr
& A_FFNAME
) && (cp
->ce_fname
!= NIL(char)) )
167 FREE( cp
->ce_fname
);
169 if( _first
!= NIL(char) ) {
170 cp
->ce_fname
= _first
;
171 cp
->ce_attr
|= A_FFNAME
;
174 cp
->ce_fname
= cp
->CE_NAME
;
175 cp
->ce_attr
&= ~A_FFNAME
;
178 if ( setlib
) cp
->ce_lib
= cp
->ce_fname
;
183 /* set it as stated only if successful, this way, we shall try again
185 if( cp
->ce_time
!= (time_t)0L ) {
186 cp
->ce_flag
|= F_STAT
;
188 /* If it is a whatif this changed scenario then return the current
189 * time, but do so only if the stat was successful. */
190 if ( (cp
->ce_attr
& A_WHATIF
) && !(cp
->ce_flag
& F_MADE
) ) {
191 cp
->ce_time
= Do_time();
200 _check_dir_list( cp
, sp
, setfname
, force
)/*
201 ============================================
202 Check the list of dir's given by the prerequisite list of sp, for a
203 file pointed at by cp. Returns 0 if path not bound, else returns
204 1 and replaces old name for cell with new cell name. */
211 /* FIXME: BCC 5.0 BUG??? If lp is assigned to a register variable then
212 * BCC 5.0 corrupts a field of the member structure when DO_STAT
213 * calls the native win95 stat system call. Blech!!!
215 * Making this a static variable forces it out of a register and
216 * seems to avoid the problem. */
224 DB_ENTER( "_check_dir_list" );
225 DB_PRINT( "mem", ("%s:-> mem %ld", cp
->CE_NAME
, (long) coreleft()) );
227 if( sp
->ce_prq
!= NIL(LINK
) ) /* check prerequisites if any */
229 /* Use the real name instead of basename, this prevents silly
230 * loops in inference code, and is consistent with man page */
233 /* Here we loop through each directory on the list, and try to stat
234 * the target. We always save the first pathname we try to stat in
235 * _first. If we subsequently get a match we then replace the value of
236 * _first by the matched path name. */
238 for( lp
=sp
->CE_PRQ
; lp
!= NIL(LINK
) && !res
; lp
=lp
->cl_next
) {
240 dir
= lp
->cl_prq
->CE_NAME
;
242 if( strchr( dir
, '$' ) ) dir
= Expand(dir
);
243 if( strcmp( dir
, ".NULL" ) == 0 ) {
247 path
= DmStrDup(Build_path(dir
,name
));
250 res
= ((cp
->ce_time
=DO_STAT(path
,NIL(char),NIL(char *),force
))!=(time_t)0L);
252 /* Have to use DmStrDup to set _first since Build_path, builds it's
253 * path names inside a static buffer. */
255 if( (_first
== NIL(char) && !fset
) || res
) {
256 if( _first
!= NIL(char) ) FREE( _first
);
266 DB_PRINT( "stat", ("_first [%s], path [%s]", _first
, path
) );
267 if( dir
!= lp
->cl_prq
->CE_NAME
) FREE(dir
);
268 if( path
&& path
!= cp
->CE_NAME
) FREE(path
);
272 DB_PRINT( "mem", ("%s:-< mem %ld", cp
->CE_NAME
, (long) coreleft()) );