1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * rep.c 28 * 29 * This file handles the .nse_depinfo file 30 */ 31 32 /* 33 * Included files 34 */ 35 #include <mk/defs.h> 36 #include <mksh/misc.h> /* retmem() */ 37 #include <vroot/report.h> /* NSE_DEPINFO */ 38 39 /* 40 * Static variables 41 */ 42 static Recursive_make recursive_list; 43 static Recursive_make *bpatch = &recursive_list; 44 static Boolean changed; 45 46 /* 47 * File table of contents 48 */ 49 50 51 /* 52 * report_recursive_init() 53 * 54 * Read the .nse_depinfo file and make a list of all the 55 * .RECURSIVE entries. 56 * 57 * Parameters: 58 * 59 * Static variables used: 60 * bpatch Points to slot where next cell should be added 61 * 62 * Global variables used: 63 * recursive_name The Name ".RECURSIVE", compared against 64 */ 65 66 void 67 report_recursive_init(void) 68 { 69 char *search_dir; 70 char nse_depinfo[MAXPATHLEN]; 71 FILE *fp; 72 int line_size, line_index; 73 wchar_t *line; 74 wchar_t *bigger_line; 75 wchar_t *colon; 76 wchar_t *dollar; 77 Recursive_make rp; 78 79 /* 80 * This routine can be called more than once, don't do 81 * anything after the first time. 82 */ 83 if (depinfo_already_read) { 84 return; 85 } else { 86 depinfo_already_read = true; 87 } 88 89 search_dir = getenv("NSE_DEP"); 90 if (search_dir == NULL) { 91 return; 92 } 93 (void) sprintf(nse_depinfo, "%s/%s", search_dir, NSE_DEPINFO); 94 fp = fopen(nse_depinfo, "r"); 95 if (fp == NULL) { 96 return; 97 } 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') { 106 continue; 107 } 108 bigger_line = ALLOC_WC(2 * line_size); 109 wcscpy(bigger_line, line); 110 retmem(line); 111 line = bigger_line; 112 if (fgetws(&line[line_index], line_size, fp) == NULL) 113 continue; 114 line_index = 2 * line_index; 115 line_size = 2 * line_size; 116 } 117 118 colon = (wchar_t *) wcschr(line, (int) colon_char); 119 if (colon == NULL) { 120 continue; 121 } 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)) { 126 /* 127 * If this entry is an old entry, ignore it 128 */ 129 MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); 130 if (dollar == NULL || 131 !IS_WEQUALN(wcs_buffer, (dollar+1) - VER_LEN, VER_LEN)){ 132 continue; 133 } 134 rp = ALLOC(Recursive_make); 135 (void) memset((char *) rp, 0, sizeof (Recursive_make_rec)); 136 /* 137 * set conditional_macro_string if string is present 138 */ 139 rp->oldline = (wchar_t *) wcsdup(line); 140 if ( dollar != NULL ){ 141 rp->cond_macrostring = 142 (wchar_t *) wcsdup(dollar - VER_LEN + 1); 143 } 144 /* 145 * get target name into recursive struct 146 */ 147 *colon = (int) nul_char; 148 rp->target = (wchar_t *) wcsdup(line); 149 *bpatch = rp; 150 bpatch = &rp->next; 151 } 152 } 153 (void) fclose(fp); 154 } 155 156 /* 157 * report_recursive_dep(target, line) 158 * 159 * Report a target as recursive. 160 * 161 * Parameters: 162 * line Dependency line reported 163 * 164 * Static variables used: 165 * bpatch Points to slot where next cell should be added 166 * changed Written if report set changed 167 */ 168 void 169 report_recursive_dep(Name target, wchar_t *line) 170 { 171 Recursive_make rp; 172 wchar_t rec_buf[STRING_BUFFER_LENGTH]; 173 String_rec string; 174 175 INIT_STRING_FROM_STACK(string, rec_buf); 176 cond_macros_into_string(target, &string); 177 /* 178 * find an applicable recursive entry, if there isn't one, create it 179 */ 180 rp = find_recursive_target(target); 181 if (rp == NULL) { 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 185 rp->target = wcb; 186 rp->newline = (wchar_t *) wcsdup(line); 187 rp->cond_macrostring = (wchar_t *) wcsdup(rec_buf); 188 *bpatch = rp; 189 bpatch = &rp->next; 190 changed = true; 191 } else { 192 if ((rp->oldline != NULL) && !IS_WEQUAL(rp->oldline, line)) { 193 rp->newline = (wchar_t *) wcsdup(line); 194 changed = true; 195 } 196 rp->removed = false; 197 } 198 } 199 200 /* 201 * find_recursive_target(target) 202 * 203 * Search the list for a given target. 204 * 205 * Return value: 206 * The target cell 207 * 208 * Parameters: 209 * target The target we need 210 * top_level_target more info used to determinde the 211 * target we need 212 * 213 * Static variables used: 214 * recursive_list The list of targets 215 */ 216 Recursive_make 217 find_recursive_target(Name target) 218 { 219 Recursive_make rp; 220 String_rec string; 221 wchar_t rec_buf[STRING_BUFFER_LENGTH]; 222 223 INIT_STRING_FROM_STACK(string, rec_buf); 224 cond_macros_into_string(target, &string); 225 226 Wstring tstr(target); 227 wchar_t * wcb = tstr.get_string(); 228 for (rp = recursive_list; rp != NULL; rp = rp->next) { 229 /* 230 * If this entry has already been removed, ignore it. 231 */ 232 if (rp->removed) 233 continue; 234 /* 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. 240 */ 241 if (IS_WEQUAL(rp->target, wcb)) { 242 if (rp->cond_macrostring[VER_LEN] == '\0' && 243 string.buffer.start[VER_LEN] != '\0'){ 244 rp->removed = true; 245 continue; 246 } else if (rp->cond_macrostring[VER_LEN] != '\0' && 247 string.buffer.start[VER_LEN] == '\0'){ 248 rp->removed = true; 249 continue; 250 } 251 } 252 /* 253 * If this is not a VERS2 entry, only need to match 254 * the target name. toptarg information from VERS1 entries 255 * are ignored. 256 */ 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)) { 262 return rp; 263 } 264 } else { 265 if (IS_WEQUAL(rp->target, wcb)) { 266 return rp; 267 } 268 } 269 } 270 return NULL; 271 } 272 273 /* 274 * remove_recursive_dep(target, top_level_target) 275 * 276 * Mark a target as no longer recursive. 277 * 278 * Parameters: 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 282 * 283 * Static variables used: 284 * changed Written if report set changed 285 */ 286 void 287 remove_recursive_dep(Name target) 288 { 289 Recursive_make rp; 290 291 rp = find_recursive_target(target); 292 293 if ( rp != NULL ) { 294 rp->removed = true; 295 changed = true; 296 if(rp->target) { 297 retmem(rp->target); 298 rp->target = NULL; 299 } 300 if(rp->newline) { 301 retmem(rp->newline); 302 rp->newline = NULL; 303 } 304 if(rp->oldline) { 305 retmem(rp->oldline); 306 rp->oldline = NULL; 307 } 308 if(rp->cond_macrostring) { 309 retmem(rp->cond_macrostring); 310 rp->cond_macrostring = NULL; 311 } 312 } 313 } 314 315 316 /* gather_recursive_deps() 317 * 318 * Create or update list of recursive targets. 319 */ 320 void 321 gather_recursive_deps(void) 322 { 323 Name_set::iterator np, e; 324 String_rec rec; 325 wchar_t rec_buf[STRING_BUFFER_LENGTH]; 326 Property lines; 327 Boolean has_recursive; 328 Dependency dp; 329 330 report_recursive_init(); 331 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; 336 /* 337 * start .RECURSIVE line with target: 338 */ 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); 343 344 for (lines = get_prop(np->prop,recursive_prop); 345 lines != NULL; 346 lines = get_prop(lines->next, recursive_prop)) { 347 /* 348 * if entry is already in depinfo 349 * file or entry was not built, ignore it 350 */ 351 if (lines->body.recursive.in_depinfo) 352 continue; 353 if (!lines->body.recursive.has_built) 354 continue; 355 has_recursive = true; 356 lines->body.recursive.in_depinfo=true; 357 358 /* 359 * Write the remainder of the 360 * .RECURSIVE line 361 */ 362 APPEND_NAME(recursive_name, &rec, 363 FIND_LENGTH); 364 append_char((int) space_char, &rec); 365 APPEND_NAME(lines->body.recursive.directory, 366 &rec, FIND_LENGTH); 367 append_char((int) space_char, &rec); 368 APPEND_NAME(lines->body.recursive.target, 369 &rec, FIND_LENGTH); 370 append_char((int) space_char, &rec); 371 372 /* Complete list of makefiles used */ 373 for (dp = lines->body.recursive.makefiles; 374 dp != NULL; 375 dp = dp->next) { 376 APPEND_NAME(dp->name, &rec, FIND_LENGTH); 377 append_char((int) space_char, &rec); 378 } 379 } 380 /* 381 * dump list of conditional targets, 382 * and report recursive entry, if needed 383 */ 384 cond_macros_into_string(np, &rec); 385 if (has_recursive){ 386 report_recursive_dep(np, rec.buffer.start); 387 } 388 389 } else if ( np->has_built ) { 390 remove_recursive_dep(np); 391 } 392 } 393 } 394 395