mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2024-12-27 22:14:57 +03:00
224 lines
5.7 KiB
C
224 lines
5.7 KiB
C
/*
|
|
* Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
|
|
*
|
|
* This file is part of Jam - see jam.c for Copyright information.
|
|
*/
|
|
|
|
/* This file is ALSO:
|
|
* Copyright 2001-2004 David Abrahams.
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
|
|
#include "jam.h"
|
|
#include "lists.h"
|
|
#include "search.h"
|
|
#include "timestamp.h"
|
|
#include "pathsys.h"
|
|
#include "variable.h"
|
|
#include "newstr.h"
|
|
#include "compile.h"
|
|
#include "strings.h"
|
|
#include "hash.h"
|
|
#include "filesys.h"
|
|
#include <string.h>
|
|
|
|
|
|
typedef struct _binding
|
|
{
|
|
char * binding;
|
|
char * target;
|
|
} BINDING;
|
|
|
|
static struct hash *explicit_bindings = 0;
|
|
|
|
|
|
void call_bind_rule
|
|
(
|
|
char * target_,
|
|
char * boundname_
|
|
)
|
|
{
|
|
LIST * bind_rule = var_get( "BINDRULE" );
|
|
if ( bind_rule )
|
|
{
|
|
/* No guarantee that the target is an allocated string, so be on the
|
|
* safe side.
|
|
*/
|
|
char * target = copystr( target_ );
|
|
|
|
/* Likewise, do not rely on implementation details of newstr.c: allocate
|
|
* a copy of boundname.
|
|
*/
|
|
char * boundname = copystr( boundname_ );
|
|
if ( boundname && target )
|
|
{
|
|
/* Prepare the argument list. */
|
|
FRAME frame[1];
|
|
frame_init( frame );
|
|
|
|
/* First argument is the target name. */
|
|
lol_add( frame->args, list_new( L0, target ) );
|
|
|
|
lol_add( frame->args, list_new( L0, boundname ) );
|
|
if ( lol_get( frame->args, 1 ) )
|
|
evaluate_rule( bind_rule->string, frame );
|
|
|
|
/* Clean up */
|
|
frame_free( frame );
|
|
}
|
|
else
|
|
{
|
|
if ( boundname )
|
|
freestr( boundname );
|
|
if ( target )
|
|
freestr( target );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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 **another_target,
|
|
int file
|
|
)
|
|
{
|
|
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 */
|
|
|
|
path_parse( target, f );
|
|
|
|
f->f_grist.ptr = 0;
|
|
f->f_grist.len = 0;
|
|
|
|
if ( ( varlist = var_get( "LOCATE" ) ) )
|
|
{
|
|
f->f_root.ptr = varlist->string;
|
|
f->f_root.len = strlen( varlist->string );
|
|
|
|
path_build( f, buf, 1 );
|
|
|
|
if ( DEBUG_SEARCH )
|
|
printf( "locate %s: %s\n", target, buf->value );
|
|
|
|
explicitly_located = 1;
|
|
|
|
timestamp( buf->value, time );
|
|
found = 1;
|
|
}
|
|
else if ( ( varlist = var_get( "SEARCH" ) ) )
|
|
{
|
|
while ( varlist )
|
|
{
|
|
BINDING b, *ba = &b;
|
|
file_info_t *ff;
|
|
|
|
f->f_root.ptr = varlist->string;
|
|
f->f_root.len = strlen( varlist->string );
|
|
|
|
string_truncate( buf, 0 );
|
|
path_build( f, buf, 1 );
|
|
|
|
if ( DEBUG_SEARCH )
|
|
printf( "search %s: %s\n", target, buf->value );
|
|
|
|
ff = file_query(buf->value);
|
|
timestamp( buf->value, 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 ( ff && ff->time )
|
|
{
|
|
if ( !file || ff->is_file )
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
varlist = list_next( varlist );
|
|
}
|
|
}
|
|
|
|
if ( !found )
|
|
{
|
|
/* Look for the obvious */
|
|
/* This is a questionable move. Should we look in the */
|
|
/* obvious place if SEARCH is set? */
|
|
|
|
f->f_root.ptr = 0;
|
|
f->f_root.len = 0;
|
|
|
|
string_truncate( buf, 0 );
|
|
path_build( f, buf, 1 );
|
|
|
|
if ( DEBUG_SEARCH )
|
|
printf( "search %s: %s\n", target, buf->value );
|
|
|
|
timestamp( buf->value, time );
|
|
}
|
|
|
|
boundname = newstr( buf->value );
|
|
string_free( buf );
|
|
|
|
if ( explicitly_located )
|
|
{
|
|
BINDING b;
|
|
BINDING * ba = &b;
|
|
b.binding = boundname;
|
|
b.target = target;
|
|
/* 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 );
|
|
|
|
return boundname;
|
|
}
|