1 //
2 // aegis - project change supervisor
3 // Copyright (C) 2002-2008, 2011, 2012 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or (at
8 // your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18
19 #include <common/arglex.h>
20 #include <common/nstring/list.h>
21 #include <common/trace.h>
22 #include <common/wstring/list.h>
23 #include <libaegis/change/file.h>
24 #include <libaegis/change.h>
25 #include <libaegis/cstate.fmtgen.h>
26 #include <libaegis/os.h>
27 #include <libaegis/project/file.h>
28 #include <libaegis/project.h>
29 #include <libaegis/sub/base_relativ.h>
30 #include <libaegis/sub.h>
31
32
33 //
34 // NAME
35 // sub_base_relative - the source substitution
36 //
37 // SYNOPSIS
38 // string_ty *sub_base_relative(wstring_list_ty *arg);
39 //
40 // DESCRIPTION
41 // The sub_base_relative function implements the base_relative
42 // substitution. The base_relative substitution is replaced by the
43 // path of the source file, relative to the base of the project tree.
44 //
45 // Requires exactly one argument.
46 //
47 // ARGUMENTS
48 // arg - list of arguments, including the function name as [0]
49 //
50 // RETURNS
51 // a pointer to a string in dynamic memory;
52 // or NULL on error, setting suberr appropriately.
53 //
54
55 wstring
sub_base_relative(sub_context_ty * scp,const wstring_list & arg)56 sub_base_relative(sub_context_ty *scp, const wstring_list &arg)
57 {
58 //
59 // Find the change. If there is no change, it is also valid in
60 // the baseline context.
61 //
62 trace(("sub_base_relative()\n{\n"));
63 wstring result;
64 change::pointer cp = sub_context_change_get(scp);
65 if (!cp)
66 {
67 project *pp = sub_context_project_get(scp);
68 if (!pp)
69 {
70 scp->error_set(i18n("not valid in current context"));
71 trace(("}\n"));
72 return result;
73 }
74 cp = pp->change_get();
75 }
76
77 //
78 // make sure we like the arguments.
79 //
80 if (arg.size() < 2)
81 {
82 scp->error_set(i18n("requires one argument"));
83 trace(("}\n"));
84 return result;
85 }
86
87 //
88 // make sure we are in an appropriate state
89 //
90 cstate_ty *cstate_data = cp->cstate_get();
91 if (cstate_data->state == cstate_state_awaiting_development)
92 {
93 scp->error_set(i18n("not valid in current context"));
94 trace(("}\n"));
95 return result;
96 }
97
98 //
99 // Get the search path.
100 //
101 string_list_ty search_path;
102 if (cstate_data->state == cstate_state_completed)
103 cp->pp->search_path_get(&search_path, false);
104 else
105 cp->search_path_get(&search_path, false);
106
107 //
108 // Turn the file name into an absolute path.
109 //
110 nstring_list results;
111 for (size_t k = 1; k < arg.size(); ++k)
112 {
113 nstring fn = arg[k].to_nstring();
114 change_become(cp);
115 nstring s = os_pathname(fn, true);
116 change_become_undo(cp);
117 fn = s;
118
119 //
120 // Hunt down the search list, to see if the file is in any of those
121 // directories.
122 //
123 for (size_t j = 0; j < search_path.nstrings; ++j)
124 {
125 s = os_below_dir(nstring(search_path.string[j]), fn);
126 if (!s.empty())
127 {
128 fn = s;
129 break;
130 }
131 }
132 results.push_back(fn);
133 }
134
135 //
136 // build the result
137 //
138 nstring s = results.unsplit();
139 result = wstring(s);
140
141 //
142 // here for all exits
143 //
144 trace(("return %p;\n", result.get_ref()));
145 trace(("}\n"));
146 return result;
147 }
148
149
150 // vim: set ts=8 sw=4 et :
151