sync master with lastest vba changes
[ooovba.git] / dmake / stat.c
blobf089119433daf145f61e86c2863be4548e223d7e
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
13 -- WWW
14 -- http://dmake.wticorp.com/
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.
23 -- LOG
24 -- Use cvs log to obtain detailed change logs.
27 #include "extern.h"
30 static int _check_dir_list ANSI((CELLPTR, CELLPTR, int, int));
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;
41 time_t res;
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) );
47 DB_RETURN( res );
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
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. */
58 PUBLIC void
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
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.
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. */
87 CELLPTR cp;
88 int setfname;
89 int force;
91 register HASHPTR hp;
92 static HASHPTR srchp = NIL(HASH);
93 char *name;
94 char *tmp;
95 int res = 0;
97 DB_ENTER( "Stat_target" );
99 name = cp->CE_NAME;
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 );
124 FREE( name );
125 name = cp->CE_NAME = tmp;
126 cp->ce_attr &= ~(A_FFNAME | A_SYMBOL);
128 else
129 { DB_VOID_RETURN; }
132 _first = NIL(char);
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 ) {
148 char *tmplib;
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 );
161 FREE( tmp );
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;
173 else {
174 cp->ce_fname = cp->CE_NAME;
175 cp->ce_attr &= ~A_FFNAME;
178 if ( setlib ) cp->ce_lib = cp->ce_fname;
180 else if( _first )
181 FREE( _first );
183 /* set it as stated only if successful, this way, we shall try again
184 * later. */
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();
195 DB_VOID_RETURN;
199 static int
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. */
206 CELLPTR cp;
207 CELLPTR sp;
208 int setfname;
209 int force;
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. */
217 static LINKPTR lp;
218 char *dir;
219 char *path;
220 char *name;
221 int res = 0;
222 int fset = 0;
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 */
231 name = cp->CE_NAME;
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 ) {
239 int nodup = 0;
240 dir = lp->cl_prq->CE_NAME;
242 if( strchr( dir, '$' ) ) dir = Expand(dir);
243 if( strcmp( dir, ".NULL" ) == 0 ) {
244 nodup = 1;
245 path = cp->CE_NAME;
246 } else {
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. */
254 if( setfname )
255 if( (_first == NIL(char) && !fset) || res ) {
256 if( _first != NIL(char) ) FREE( _first );
257 if (nodup)
258 _first = NIL(char);
259 else {
260 _first = path;
261 path = NIL(char);
263 fset = 1;
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()) );
273 DB_RETURN( res );