4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * This file handles the .nse_depinfo file
36 #include <mksh/misc.h> /* retmem() */
37 #include <vroot/report.h> /* NSE_DEPINFO */
42 static Recursive_make recursive_list
;
43 static Recursive_make
*bpatch
= &recursive_list
;
44 static Boolean changed
;
47 * File table of contents
52 * report_recursive_init()
54 * Read the .nse_depinfo file and make a list of all the
59 * Static variables used:
60 * bpatch Points to slot where next cell should be added
62 * Global variables used:
63 * recursive_name The Name ".RECURSIVE", compared against
67 report_recursive_init(void)
70 char nse_depinfo
[MAXPATHLEN
];
72 int line_size
, line_index
;
80 * This routine can be called more than once, don't do
81 * anything after the first time.
83 if (depinfo_already_read
) {
86 depinfo_already_read
= true;
89 search_dir
= getenv("NSE_DEP");
90 if (search_dir
== NULL
) {
93 (void) sprintf(nse_depinfo
, "%s/%s", search_dir
, NSE_DEPINFO
);
94 fp
= fopen(nse_depinfo
, "r");
98 line_size
= MAXPATHLEN
;
99 line_index
= line_size
- 1;
100 line
= ALLOC_WC(line_size
);
101 Wstring
rns(recursive_name
);
102 wchar_t * wcb
= rns
.get_string();
103 while (fgetws(line
, line_size
, fp
) != NULL
) {
104 while (wcslen(line
) == line_index
) {
105 if (line
[wcslen(line
) - 1] == '\n') {
108 bigger_line
= ALLOC_WC(2 * line_size
);
109 wcscpy(bigger_line
, line
);
112 if (fgetws(&line
[line_index
], line_size
, fp
) == NULL
)
114 line_index
= 2 * line_index
;
115 line_size
= 2 * line_size
;
118 colon
= (wchar_t *) wcschr(line
, (int) colon_char
);
122 dollar
= (wchar_t *) wcschr(line
, (int) dollar_char
);
123 line
[wcslen(line
) - 1] = (int) nul_char
;
124 if (IS_WEQUALN(&colon
[2], wcb
,
125 (int) recursive_name
->hash
.length
)) {
127 * If this entry is an old entry, ignore it
129 MBSTOWCS(wcs_buffer
, DEPINFO_FMT_VERSION
);
130 if (dollar
== NULL
||
131 !IS_WEQUALN(wcs_buffer
, (dollar
+1) - VER_LEN
, VER_LEN
)){
134 rp
= ALLOC(Recursive_make
);
135 (void) memset((char *) rp
, 0, sizeof (Recursive_make_rec
));
137 * set conditional_macro_string if string is present
139 rp
->oldline
= (wchar_t *) wcsdup(line
);
140 if ( dollar
!= NULL
){
141 rp
->cond_macrostring
=
142 (wchar_t *) wcsdup(dollar
- VER_LEN
+ 1);
145 * get target name into recursive struct
147 *colon
= (int) nul_char
;
148 rp
->target
= (wchar_t *) wcsdup(line
);
157 * report_recursive_dep(target, line)
159 * Report a target as recursive.
162 * line Dependency line reported
164 * Static variables used:
165 * bpatch Points to slot where next cell should be added
166 * changed Written if report set changed
169 report_recursive_dep(Name target
, wchar_t *line
)
172 wchar_t rec_buf
[STRING_BUFFER_LENGTH
];
175 INIT_STRING_FROM_STACK(string
, rec_buf
);
176 cond_macros_into_string(target
, &string
);
178 * find an applicable recursive entry, if there isn't one, create it
180 rp
= find_recursive_target(target
);
182 rp
= ALLOC(Recursive_make
);
183 (void) memset((char *) rp
, 0, sizeof (Recursive_make_rec
));
184 wchar_t * wcb
= get_wstring(target
->string_mb
); // XXX Tolik: needs retmem
186 rp
->newline
= (wchar_t *) wcsdup(line
);
187 rp
->cond_macrostring
= (wchar_t *) wcsdup(rec_buf
);
192 if ((rp
->oldline
!= NULL
) && !IS_WEQUAL(rp
->oldline
, line
)) {
193 rp
->newline
= (wchar_t *) wcsdup(line
);
201 * find_recursive_target(target)
203 * Search the list for a given target.
209 * target The target we need
210 * top_level_target more info used to determinde the
213 * Static variables used:
214 * recursive_list The list of targets
217 find_recursive_target(Name target
)
221 wchar_t rec_buf
[STRING_BUFFER_LENGTH
];
223 INIT_STRING_FROM_STACK(string
, rec_buf
);
224 cond_macros_into_string(target
, &string
);
226 Wstring
tstr(target
);
227 wchar_t * wcb
= tstr
.get_string();
228 for (rp
= recursive_list
; rp
!= NULL
; rp
= rp
->next
) {
230 * If this entry has already been removed, ignore it.
235 * If this target, and the target on the list are the same
236 * and if one of them contains conditional macro info, while
237 * the other doesn't, remove this entry from the list of
238 * recursive entries. This can only happen if the Makefile
239 * has changed to no longer contain conditional macros.
241 if (IS_WEQUAL(rp
->target
, wcb
)) {
242 if (rp
->cond_macrostring
[VER_LEN
] == '\0' &&
243 string
.buffer
.start
[VER_LEN
] != '\0'){
246 } else if (rp
->cond_macrostring
[VER_LEN
] != '\0' &&
247 string
.buffer
.start
[VER_LEN
] == '\0'){
253 * If this is not a VERS2 entry, only need to match
254 * the target name. toptarg information from VERS1 entries
257 MBSTOWCS(wcs_buffer
, DEPINFO_FMT_VERSION
);
258 if (IS_WEQUALN(wcs_buffer
, string
.buffer
.start
, VER_LEN
)) {
259 if (IS_WEQUAL(rp
->cond_macrostring
,
260 string
.buffer
.start
) &&
261 IS_WEQUAL(rp
->target
, wcb
)) {
265 if (IS_WEQUAL(rp
->target
, wcb
)) {
274 * remove_recursive_dep(target, top_level_target)
276 * Mark a target as no longer recursive.
279 * target The target we want to remove
280 * top_level_target target we want to remove must be built from
281 * the same top level target
283 * Static variables used:
284 * changed Written if report set changed
287 remove_recursive_dep(Name target
)
291 rp
= find_recursive_target(target
);
308 if(rp
->cond_macrostring
) {
309 retmem(rp
->cond_macrostring
);
310 rp
->cond_macrostring
= NULL
;
316 /* gather_recursive_deps()
318 * Create or update list of recursive targets.
321 gather_recursive_deps(void)
323 Name_set::iterator np
, e
;
325 wchar_t rec_buf
[STRING_BUFFER_LENGTH
];
326 register Property lines
;
327 Boolean has_recursive
;
330 report_recursive_init();
332 /* Go thru all targets and dump recursive dependencies */
333 for (np
= hashtab
.begin(), e
= hashtab
.end(); np
!= e
; np
++) {
334 if (np
->has_recursive_dependency
){
335 has_recursive
= false;
337 * start .RECURSIVE line with target:
339 INIT_STRING_FROM_STACK(rec
, rec_buf
);
340 APPEND_NAME(np
, &rec
, FIND_LENGTH
);
341 append_char((int) colon_char
, &rec
);
342 append_char((int) space_char
, &rec
);
344 for (lines
= get_prop(np
->prop
,recursive_prop
);
346 lines
= get_prop(lines
->next
, recursive_prop
)) {
348 * if entry is already in depinfo
349 * file or entry was not built, ignore it
351 if (lines
->body
.recursive
.in_depinfo
)
353 if (!lines
->body
.recursive
.has_built
)
355 has_recursive
= true;
356 lines
->body
.recursive
.in_depinfo
=true;
359 * Write the remainder of the
362 APPEND_NAME(recursive_name
, &rec
,
364 append_char((int) space_char
, &rec
);
365 APPEND_NAME(lines
->body
.recursive
.directory
,
367 append_char((int) space_char
, &rec
);
368 APPEND_NAME(lines
->body
.recursive
.target
,
370 append_char((int) space_char
, &rec
);
372 /* Complete list of makefiles used */
373 for (dp
= lines
->body
.recursive
.makefiles
;
376 APPEND_NAME(dp
->name
, &rec
, FIND_LENGTH
);
377 append_char((int) space_char
, &rec
);
381 * dump list of conditional targets,
382 * and report recursive entry, if needed
384 cond_macros_into_string(np
, &rec
);
386 report_recursive_dep(np
, rec
.buffer
.start
);
389 } else if ( np
->has_built
) {
390 remove_recursive_dep(np
);