Line data Source code
1 : /* RCS $Id: stat.c,v 1.3 2007-10-15 15:41:38 ihi Exp $
2 : --
3 : -- SYNOPSIS
4 : -- Bind a target name to a file.
5 : --
6 : -- DESCRIPTION
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.
9 : --
10 : -- AUTHOR
11 : -- Dennis Vadura, dvadura@dmake.wticorp.com
12 : --
13 : -- WWW
14 : -- http://dmake.wticorp.com/
15 : --
16 : -- COPYRIGHT
17 : -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
18 : --
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.
22 : --
23 : -- LOG
24 : -- Use cvs log to obtain detailed change logs.
25 : */
26 :
27 : #include "extern.h"
28 :
29 :
30 : static int _check_dir_list ANSI((CELLPTR, CELLPTR, int, int));
31 :
32 : #ifdef DBUG
33 : /* Just a little ditty for debugging this thing */
34 : static time_t
35 : _do_stat( name, lib, sym, force )
36 : char *name;
37 : char *lib;
38 : char **sym;
39 : int force;
40 : {
41 : time_t res;
42 : DB_ENTER( "_do_stat" );
43 :
44 : res = Do_stat(name, lib, sym, force);
45 : DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) );
46 :
47 : DB_RETURN( res );
48 : }
49 : #define DO_STAT(A,B,C,D) _do_stat(A,B,C,D)
50 : #else
51 : #define DO_STAT(A,B,C,D) Do_stat(A,B,C,D)
52 : #endif
53 :
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. */
57 :
58 : PUBLIC void
59 37761 : 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)
64 :
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
77 : applied.
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.
83 :
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. */
86 :
87 : CELLPTR cp;
88 : int setfname;
89 : int force;
90 : {
91 : register HASHPTR hp;
92 : static HASHPTR srchp = NIL(HASH);
93 : char *name;
94 : char *tmp;
95 37761 : int res = 0;
96 :
97 : DB_ENTER( "Stat_target" );
98 :
99 37761 : name = cp->CE_NAME;
100 : DB_PRINT( "stat", ("called on [%s]", name) );
101 :
102 37761 : if( srchp == NIL(HASH) ) srchp = Get_name(".SOURCE",Defs,FALSE);
103 :
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. */
110 :
111 37761 : if( cp->ce_attr & A_SYMBOL ) {
112 : DB_PRINT( "stat", ("Binding lib symbol [%s]", name) );
113 :
114 0 : cp->ce_time = DO_STAT( name, cp->ce_lib, &tmp, force );
115 :
116 0 : 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 */
119 :
120 0 : if( Verbose & V_MAKE )
121 0 : printf( "%s: Mapped ((%s)) to %s(%s)\n", Pname,
122 : name, cp->ce_lib, tmp );
123 :
124 0 : FREE( name );
125 0 : name = cp->CE_NAME = tmp;
126 0 : cp->ce_attr &= ~(A_FFNAME | A_SYMBOL);
127 : }
128 : else
129 : { DB_VOID_RETURN; }
130 : }
131 :
132 37761 : _first = NIL(char);
133 37761 : tmp = DmStrJoin( ".SOURCE", Get_suffix(name), -1, FALSE);
134 :
135 : /* Check .SOURCE.xxx target */
136 37761 : if( (hp = Get_name(tmp, Defs, FALSE)) != NIL(HASH) )
137 0 : res = _check_dir_list( cp, hp->CP_OWNR, setfname, force );
138 :
139 : /* Check just .SOURCE */
140 37761 : if( !res && (srchp != NIL(HASH)) )
141 37761 : res = _check_dir_list( cp, srchp->CP_OWNR, setfname, force );
142 :
143 : /* If libmember and we haven't found it check the library */
144 37761 : if( !res && (cp->ce_attr & A_LIBRARYM) ) {
145 0 : cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *), force);
146 :
147 0 : if( !cp->ce_time && Tmd && *Tmd && cp->ce_lib ) {
148 : char *tmplib;
149 0 : tmplib=DmStrDup(Build_path(Tmd,cp->ce_lib));
150 :
151 0 : if ((cp->ce_time = DO_STAT(name, tmplib, NIL(char *),force)) != (time_t)0L){
152 0 : cp->ce_lib=DmStrDup(tmplib);
153 : }
154 : }
155 :
156 0 : if( Verbose & V_MAKE )
157 0 : printf( "%s: Checking library '%s' for member [%s], time %ld\n",
158 : Pname, cp->ce_lib, name, cp->ce_time );
159 : }
160 :
161 37761 : FREE( tmp );
162 :
163 70342 : if( setfname == 1 || (setfname == -1 && cp->ce_time != (time_t)0L) ) {
164 32581 : int setlib = (cp->ce_lib == cp->ce_fname);
165 :
166 32581 : if( (cp->ce_attr & A_FFNAME) && (cp->ce_fname != NIL(char)) )
167 0 : FREE( cp->ce_fname );
168 :
169 32581 : if( _first != NIL(char) ) {
170 0 : cp->ce_fname = _first;
171 0 : cp->ce_attr |= A_FFNAME;
172 : }
173 : else {
174 32581 : cp->ce_fname = cp->CE_NAME;
175 32581 : cp->ce_attr &= ~A_FFNAME;
176 : }
177 :
178 32581 : if ( setlib ) cp->ce_lib = cp->ce_fname;
179 : }
180 5180 : else if( _first )
181 0 : FREE( _first );
182 :
183 : /* set it as stated only if successful, this way, we shall try again
184 : * later. */
185 37761 : if( cp->ce_time != (time_t)0L ) {
186 36042 : cp->ce_flag |= F_STAT;
187 :
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 36042 : if ( (cp->ce_attr & A_WHATIF) && !(cp->ce_flag & F_MADE) ) {
191 0 : cp->ce_time = Do_time();
192 : }
193 : }
194 :
195 : DB_VOID_RETURN;
196 : }
197 :
198 :
199 : static int
200 37761 : _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. */
205 :
206 : CELLPTR cp;
207 : CELLPTR sp;
208 : int setfname;
209 : int force;
210 : {
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!!!
214 : *
215 : * Making this a static variable forces it out of a register and
216 : * seems to avoid the problem. */
217 : static LINKPTR lp;
218 : char *dir;
219 : char *path;
220 : char *name;
221 37761 : int res = 0;
222 37761 : int fset = 0;
223 :
224 : DB_ENTER( "_check_dir_list" );
225 : DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
226 :
227 37761 : if( sp->ce_prq != NIL(LINK) ) /* check prerequisites if any */
228 : {
229 : /* Use the real name instead of basename, this prevents silly
230 : * loops in inference code, and is consistent with man page */
231 37761 : name = cp->CE_NAME;
232 :
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. */
237 :
238 75522 : for( lp=sp->CE_PRQ; lp != NIL(LINK) && !res; lp=lp->cl_next ) {
239 37761 : int nodup = 0;
240 37761 : dir = lp->cl_prq->CE_NAME;
241 :
242 37761 : if( strchr( dir, '$' ) ) dir = Expand(dir);
243 37761 : if( strcmp( dir, ".NULL" ) == 0 ) {
244 37761 : nodup = 1;
245 37761 : path = cp->CE_NAME;
246 : } else {
247 0 : path = DmStrDup(Build_path(dir,name));
248 : }
249 :
250 37761 : res = ((cp->ce_time=DO_STAT(path,NIL(char),NIL(char *),force))!=(time_t)0L);
251 :
252 : /* Have to use DmStrDup to set _first since Build_path, builds it's
253 : * path names inside a static buffer. */
254 37761 : if( setfname )
255 33123 : if( (_first == NIL(char) && !fset) || res ) {
256 33123 : if( _first != NIL(char) ) FREE( _first );
257 33123 : if (nodup)
258 33123 : _first = NIL(char);
259 : else {
260 0 : _first = path;
261 0 : path = NIL(char);
262 : }
263 33123 : fset = 1;
264 : }
265 :
266 : DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) );
267 37761 : if( dir != lp->cl_prq->CE_NAME ) FREE(dir);
268 37761 : if( path && path != cp->CE_NAME ) FREE(path);
269 : }
270 : }
271 :
272 : DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
273 37761 : DB_RETURN( res );
274 : }
275 :
276 :
277 :
278 :
|