//
// aegis - project change supervisor
// Copyright (C) 2002-2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//
// NAME
// sub_base_relative - the source substitution
//
// SYNOPSIS
// string_ty *sub_base_relative(wstring_list_ty *arg);
//
// DESCRIPTION
// The sub_base_relative function implements the base_relative
// substitution. The base_relative substitution is replaced by the
// path of the source file, relative to the base of the project tree.
//
// Requires exactly one argument.
//
// ARGUMENTS
// arg - list of arguments, including the function name as [0]
//
// RETURNS
// a pointer to a string in dynamic memory;
// or NULL on error, setting suberr appropriately.
//
wstring
sub_base_relative(sub_context_ty *scp, const wstring_list &arg)
{
//
// Find the change. If there is no change, it is also valid in
// the baseline context.
//
trace(("sub_base_relative()\n{\n"));
wstring result;
change::pointer cp = sub_context_change_get(scp);
if (!cp)
{
project_ty *pp = sub_context_project_get(scp);
if (!pp)
{
scp->error_set(i18n("not valid in current context"));
trace(("}\n"));
return result;
}
cp = pp->change_get();
}
//
// make sure we like the arguments.
//
if (arg.size() < 2)
{
scp->error_set(i18n("requires one argument"));
trace(("}\n"));
return result;
}
//
// make sure we are in an appropriate state
//
cstate_ty *cstate_data = cp->cstate_get();
if (cstate_data->state == cstate_state_awaiting_development)
{
scp->error_set(i18n("not valid in current context"));
trace(("}\n"));
return result;
}
//
// Get the search path.
//
string_list_ty search_path;
if (cstate_data->state == cstate_state_completed)
project_search_path_get(cp->pp, &search_path, 0);
else
change_search_path_get(cp, &search_path, 0);
//
// Turn the file name into an absolute path.
//
nstring_list results;
for (size_t k = 1; k < arg.size(); ++k)
{
nstring fn = arg[k].to_nstring();
change_become(cp);
nstring s = os_pathname(fn, true);
change_become_undo(cp);
fn = s;
//
// Hunt down the search list, to see if the file is in any of those
// directories.
//
for (size_t j = 0; j < search_path.nstrings; ++j)
{
s = os_below_dir(nstring(search_path.string[j]), fn);
if (!s.empty())
{
fn = s;
break;
}
}
results.push_back(fn);
}
//
// build the result
//
nstring s = results.unsplit();
result = wstring(s);
//
// here for all exits
//
trace(("return %8.8lX;\n", (long)result.get_ref()));
trace(("}\n"));
return result;
}