From 8bcec068c63fee37e5cdee5ef6804c0009e8a7be Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 30 Jun 2003 14:10:04 +0000 Subject: [PATCH] Change handling of generated headers to use the idea of Matt Armstrong, from jamming mailing list. * new/search.h (search): Add a new parameter 'another_target', which returns the name of a target already bound to the same location via LOCATE. * new/search.c (search): Ajust the search algorithm to check for targets bound to searched directories. [SVN r18887] --- historic/jam/src/compile.c | 4 ++- historic/jam/src/hcache.c | 4 ++- historic/jam/src/make.c | 13 +++++++- historic/jam/src/make1.c | 2 +- historic/jam/src/rules.c | 21 +++---------- historic/jam/src/search.c | 62 ++++++++++++++++++++++++++++++++++++-- historic/jam/src/search.h | 2 +- jam_src/compile.c | 4 ++- jam_src/hcache.c | 4 ++- jam_src/make.c | 13 +++++++- jam_src/make1.c | 2 +- jam_src/rules.c | 21 +++---------- jam_src/search.c | 62 ++++++++++++++++++++++++++++++++++++-- jam_src/search.h | 2 +- 14 files changed, 168 insertions(+), 48 deletions(-) diff --git a/historic/jam/src/compile.c b/historic/jam/src/compile.c index 28d830ab1..551a5817f 100644 --- a/historic/jam/src/compile.c +++ b/historic/jam/src/compile.c @@ -367,7 +367,9 @@ compile_include( /* include files are not built with make(). */ pushsettings( t->settings ); - t->boundname = search( t->name, &t->time ); + /* We don't expect that file to be included is generated by some + action. Therefore, pass 0 as third argument. */ + t->boundname = search( t->name, &t->time, 0 ); popsettings( t->settings ); parse_file( t->boundname, frame ); diff --git a/historic/jam/src/hcache.c b/historic/jam/src/hcache.c index 313425081..1c9797ddc 100644 --- a/historic/jam/src/hcache.c +++ b/historic/jam/src/hcache.c @@ -80,7 +80,9 @@ cache_name(void) TARGET *t = bindtarget( hcachevar->string ); pushsettings( t->settings ); - t->boundname = search( t->name, &t->time ); + /* Don't expect cache file to be generated, so pass 0 + as third argument to search. */ + t->boundname = search( t->name, &t->time, 0 ); popsettings( t->settings ); if (hcachevar) { diff --git a/historic/jam/src/make.c b/historic/jam/src/make.c index 7ee9c6b17..f83f7b5ca 100644 --- a/historic/jam/src/make.c +++ b/historic/jam/src/make.c @@ -264,7 +264,18 @@ make0( if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) ) { - t->boundname = search( t->name, &t->time ); + char* another_target; + t->boundname = search( t->name, &t->time, &another_target ); + /* If it was detected that this target refers to an already + existing and bound one, we add include dependency, so that + every target which depends on us will depend on that other + target. */ + if( another_target ) + { + t->deps[T_DEPS_INCLUDES] = targetlist( t->deps[T_DEPS_INCLUDES], + list_new( L0, another_target ) ); + } + t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; } diff --git a/historic/jam/src/make1.c b/historic/jam/src/make1.c index a5883ef2a..93b0f12b1 100644 --- a/historic/jam/src/make1.c +++ b/historic/jam/src/make1.c @@ -956,7 +956,7 @@ make1bind( printf( "warning: using independent target %s\n", t->name ); pushsettings( t->settings ); - t->boundname = search( t->name, &t->time ); + t->boundname = search( t->name, &t->time, 0 ); t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; popsettings( t->settings ); } diff --git a/historic/jam/src/rules.c b/historic/jam/src/rules.c index 3128ae647..e1fa3dd97 100644 --- a/historic/jam/src/rules.c +++ b/historic/jam/src/rules.c @@ -152,29 +152,18 @@ static void bind_explicitly_located_target(void* xtarget, void* data) TARGET* t = (TARGET*)xtarget; if (! (t->flags & T_FLAG_NOTFILE) ) { - /* Check if there's a setting for LOCATE_TARGET */ + /* Check if there's a setting for LOCATE */ SETTINGS* s = t->settings; for(; s ; s = s->next) { if (strcmp(s->symbol, "LOCATE") == 0) { pushsettings(t->settings); - t->boundname = search( t->name, &t->time ); - t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; + /* We're binding a target with explicit LOCATE. So + third argument is of now use: nothing will be returned + through it. */ + t->boundname = search( t->name, &t->time, 0 ); popsettings(t->settings); - - { - LOCATED_TARGET lt, *lta = < - lt.file_name = t->boundname; - lt.target = t; - if (!located_targets) - located_targets = hashinit( sizeof(LOCATED_TARGET), - "located targets" ); - - /* TODO: should check if we've entered the item or not. */ - hashenter(located_targets, (HASHDATA **)<a); - } - break; } } diff --git a/historic/jam/src/search.c b/historic/jam/src/search.c index 82e59fee3..6e1c811ef 100644 --- a/historic/jam/src/search.c +++ b/historic/jam/src/search.c @@ -21,8 +21,16 @@ # include "newstr.h" # include "compile.h" # include "strings.h" +# include "hash.h" # include +typedef struct _binding { + char* binding; + char* target; +} BINDING; + +static struct hash *explicit_bindings = 0; + void call_bind_rule( char* target_, char* boundname_ ) @@ -65,19 +73,42 @@ void call_bind_rule( /* * search.c - find a target along $(SEARCH) or $(LOCATE) + * First, check if LOCATE is set. If so, use it to determine + * the location of target and return, regardless of whether anything + * exists on that location. + * + * Second, examine all directories in SEARCH. If there's file already + * or there's another target with the same name which was placed + * to this location via LOCATE setting, stop and return the location. + * In case of previous target, return it's name via the third argument. + * + * This bevahiour allow to handle dependency on generated files. If + * caller does not expect that target is generated, 0 can be passed as + * the third argument. */ char * search( - char *target, - time_t *time ) + char *target, + time_t *time, + char **another_target +) { PATHNAME f[1]; LIST *varlist; string buf[1]; int found = 0; + /* Will be set to 1 if target location is specified via LOCATE. */ + int explicitly_located = 0; char *boundname = 0; + if( another_target ) + *another_target = 0; + + if (! explicit_bindings ) + explicit_bindings = hashinit( sizeof(BINDING), + "explicitly specified locations"); + string_new( buf ); /* Parse the filename */ @@ -96,6 +127,8 @@ search( if( DEBUG_SEARCH ) printf( "locate %s: %s\n", target, buf->value ); + explicitly_located = 1; + timestamp( buf->value, time ); found = 1; } @@ -103,6 +136,8 @@ search( { while( varlist ) { + BINDING b, *ba = &b; + f->f_root.ptr = varlist->string; f->f_root.len = strlen( varlist->string ); @@ -114,7 +149,19 @@ search( timestamp( buf->value, time ); - if( *time ) + b.binding = buf->value; + + if( hashcheck( explicit_bindings, (HASHDATA**)&ba ) ) + { + if( DEBUG_SEARCH ) + printf(" search %s: found explicitly located target %s\n", + target, ba->target); + if( another_target ) + *another_target = ba->target; + found = 1; + break; + } + else if( *time ) { found = 1; break; @@ -144,6 +191,15 @@ search( boundname = newstr( buf->value ); string_free( buf ); + + if (explicitly_located) + { + BINDING b = {boundname, target}, *ba = &b; + /* CONSIDER: we probably should issue a warning is another file + is explicitly bound to the same location. This might break + compatibility, though. */ + hashenter(explicit_bindings, (HASHDATA**)&ba); + } /* prepare a call to BINDRULE if the variable is set */ call_bind_rule( target, boundname ); diff --git a/historic/jam/src/search.h b/historic/jam/src/search.h index bb8035723..af3e890fd 100644 --- a/historic/jam/src/search.h +++ b/historic/jam/src/search.h @@ -8,4 +8,4 @@ * search.h - find a target along $(SEARCH) or $(LOCATE) */ -char *search( char *target, time_t *time ); +char *search( char *target, time_t *time, char **another_target ); diff --git a/jam_src/compile.c b/jam_src/compile.c index 28d830ab1..551a5817f 100644 --- a/jam_src/compile.c +++ b/jam_src/compile.c @@ -367,7 +367,9 @@ compile_include( /* include files are not built with make(). */ pushsettings( t->settings ); - t->boundname = search( t->name, &t->time ); + /* We don't expect that file to be included is generated by some + action. Therefore, pass 0 as third argument. */ + t->boundname = search( t->name, &t->time, 0 ); popsettings( t->settings ); parse_file( t->boundname, frame ); diff --git a/jam_src/hcache.c b/jam_src/hcache.c index 313425081..1c9797ddc 100644 --- a/jam_src/hcache.c +++ b/jam_src/hcache.c @@ -80,7 +80,9 @@ cache_name(void) TARGET *t = bindtarget( hcachevar->string ); pushsettings( t->settings ); - t->boundname = search( t->name, &t->time ); + /* Don't expect cache file to be generated, so pass 0 + as third argument to search. */ + t->boundname = search( t->name, &t->time, 0 ); popsettings( t->settings ); if (hcachevar) { diff --git a/jam_src/make.c b/jam_src/make.c index 7ee9c6b17..f83f7b5ca 100644 --- a/jam_src/make.c +++ b/jam_src/make.c @@ -264,7 +264,18 @@ make0( if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) ) { - t->boundname = search( t->name, &t->time ); + char* another_target; + t->boundname = search( t->name, &t->time, &another_target ); + /* If it was detected that this target refers to an already + existing and bound one, we add include dependency, so that + every target which depends on us will depend on that other + target. */ + if( another_target ) + { + t->deps[T_DEPS_INCLUDES] = targetlist( t->deps[T_DEPS_INCLUDES], + list_new( L0, another_target ) ); + } + t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; } diff --git a/jam_src/make1.c b/jam_src/make1.c index a5883ef2a..93b0f12b1 100644 --- a/jam_src/make1.c +++ b/jam_src/make1.c @@ -956,7 +956,7 @@ make1bind( printf( "warning: using independent target %s\n", t->name ); pushsettings( t->settings ); - t->boundname = search( t->name, &t->time ); + t->boundname = search( t->name, &t->time, 0 ); t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; popsettings( t->settings ); } diff --git a/jam_src/rules.c b/jam_src/rules.c index 3128ae647..e1fa3dd97 100644 --- a/jam_src/rules.c +++ b/jam_src/rules.c @@ -152,29 +152,18 @@ static void bind_explicitly_located_target(void* xtarget, void* data) TARGET* t = (TARGET*)xtarget; if (! (t->flags & T_FLAG_NOTFILE) ) { - /* Check if there's a setting for LOCATE_TARGET */ + /* Check if there's a setting for LOCATE */ SETTINGS* s = t->settings; for(; s ; s = s->next) { if (strcmp(s->symbol, "LOCATE") == 0) { pushsettings(t->settings); - t->boundname = search( t->name, &t->time ); - t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; + /* We're binding a target with explicit LOCATE. So + third argument is of now use: nothing will be returned + through it. */ + t->boundname = search( t->name, &t->time, 0 ); popsettings(t->settings); - - { - LOCATED_TARGET lt, *lta = < - lt.file_name = t->boundname; - lt.target = t; - if (!located_targets) - located_targets = hashinit( sizeof(LOCATED_TARGET), - "located targets" ); - - /* TODO: should check if we've entered the item or not. */ - hashenter(located_targets, (HASHDATA **)<a); - } - break; } } diff --git a/jam_src/search.c b/jam_src/search.c index 82e59fee3..6e1c811ef 100644 --- a/jam_src/search.c +++ b/jam_src/search.c @@ -21,8 +21,16 @@ # include "newstr.h" # include "compile.h" # include "strings.h" +# include "hash.h" # include +typedef struct _binding { + char* binding; + char* target; +} BINDING; + +static struct hash *explicit_bindings = 0; + void call_bind_rule( char* target_, char* boundname_ ) @@ -65,19 +73,42 @@ void call_bind_rule( /* * search.c - find a target along $(SEARCH) or $(LOCATE) + * First, check if LOCATE is set. If so, use it to determine + * the location of target and return, regardless of whether anything + * exists on that location. + * + * Second, examine all directories in SEARCH. If there's file already + * or there's another target with the same name which was placed + * to this location via LOCATE setting, stop and return the location. + * In case of previous target, return it's name via the third argument. + * + * This bevahiour allow to handle dependency on generated files. If + * caller does not expect that target is generated, 0 can be passed as + * the third argument. */ char * search( - char *target, - time_t *time ) + char *target, + time_t *time, + char **another_target +) { PATHNAME f[1]; LIST *varlist; string buf[1]; int found = 0; + /* Will be set to 1 if target location is specified via LOCATE. */ + int explicitly_located = 0; char *boundname = 0; + if( another_target ) + *another_target = 0; + + if (! explicit_bindings ) + explicit_bindings = hashinit( sizeof(BINDING), + "explicitly specified locations"); + string_new( buf ); /* Parse the filename */ @@ -96,6 +127,8 @@ search( if( DEBUG_SEARCH ) printf( "locate %s: %s\n", target, buf->value ); + explicitly_located = 1; + timestamp( buf->value, time ); found = 1; } @@ -103,6 +136,8 @@ search( { while( varlist ) { + BINDING b, *ba = &b; + f->f_root.ptr = varlist->string; f->f_root.len = strlen( varlist->string ); @@ -114,7 +149,19 @@ search( timestamp( buf->value, time ); - if( *time ) + b.binding = buf->value; + + if( hashcheck( explicit_bindings, (HASHDATA**)&ba ) ) + { + if( DEBUG_SEARCH ) + printf(" search %s: found explicitly located target %s\n", + target, ba->target); + if( another_target ) + *another_target = ba->target; + found = 1; + break; + } + else if( *time ) { found = 1; break; @@ -144,6 +191,15 @@ search( boundname = newstr( buf->value ); string_free( buf ); + + if (explicitly_located) + { + BINDING b = {boundname, target}, *ba = &b; + /* CONSIDER: we probably should issue a warning is another file + is explicitly bound to the same location. This might break + compatibility, though. */ + hashenter(explicit_bindings, (HASHDATA**)&ba); + } /* prepare a call to BINDRULE if the variable is set */ call_bind_rule( target, boundname ); diff --git a/jam_src/search.h b/jam_src/search.h index bb8035723..af3e890fd 100644 --- a/jam_src/search.h +++ b/jam_src/search.h @@ -8,4 +8,4 @@ * search.h - find a target along $(SEARCH) or $(LOCATE) */ -char *search( char *target, time_t *time ); +char *search( char *target, time_t *time, char **another_target );