diff options
author | Igor Pashev <igor.pashev@nexenta.com> | 2012-06-29 14:36:07 +0400 |
---|---|---|
committer | Igor Pashev <igor.pashev@nexenta.com> | 2012-06-29 14:36:07 +0400 |
commit | e0463df9c3d2ee6155221cc443c571d5da47098a (patch) | |
tree | 5c6b99e64c1b65d986e2722728c74f202a578be6 /usr/src/make_src/Make/bin/make/common/rep.cc | |
download | sunmake-orig.tar.gz |
Initial import of DevPro make sourcesorig
Downloaded from http://dlc.sun.com/osol/devpro/downloads/current/
Licensed under CDDL http://www.opensource.org/licenses/CDDL-1.0
Diffstat (limited to 'usr/src/make_src/Make/bin/make/common/rep.cc')
-rw-r--r-- | usr/src/make_src/Make/bin/make/common/rep.cc | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/usr/src/make_src/Make/bin/make/common/rep.cc b/usr/src/make_src/Make/bin/make/common/rep.cc new file mode 100644 index 0000000..6ad4007 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/rep.cc @@ -0,0 +1,529 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)rep.cc 1.25 06/12/12 + */ + +#pragma ident "@(#)rep.cc 1.25 06/12/12" + +/* + * rep.c + * + * This file handles the .nse_depinfo file + */ + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/misc.h> /* retmem() */ +#include <vroot/report.h> /* NSE_DEPINFO */ + +/* + * Static variables + */ +static Recursive_make recursive_list; +static Recursive_make *bpatch = &recursive_list; +static Boolean changed; + +/* + * File table of contents + */ + + +/* + * report_recursive_init() + * + * Read the .nse_depinfo file and make a list of all the + * .RECURSIVE entries. + * + * Parameters: + * + * Static variables used: + * bpatch Points to slot where next cell should be added + * + * Global variables used: + * recursive_name The Name ".RECURSIVE", compared against + */ + +void +report_recursive_init(void) +{ + char *search_dir; + char nse_depinfo[MAXPATHLEN]; + FILE *fp; + int line_size, line_index; + wchar_t *line; + wchar_t *bigger_line; + wchar_t *colon; + wchar_t *dollar; + Recursive_make rp; + + /* + * This routine can be called more than once, don't do + * anything after the first time. + */ + if (depinfo_already_read) { + return; + } else { + depinfo_already_read = true; + } + + search_dir = getenv(NOCATGETS("NSE_DEP")); + if (search_dir == NULL) { + return; + } + (void) sprintf(nse_depinfo, "%s/%s", search_dir, NSE_DEPINFO); + fp = fopen(nse_depinfo, "r"); + if (fp == NULL) { + return; + } + line_size = MAXPATHLEN; + line_index = line_size - 1; + line = ALLOC_WC(line_size); + Wstring rns(recursive_name); + wchar_t * wcb = rns.get_string(); + while (fgetws(line, line_size, fp) != NULL) { + while (wslen(line) == line_index) { + if (line[wslen(line) - 1] == '\n') { + continue; + } + bigger_line = ALLOC_WC(2 * line_size); + wscpy(bigger_line, line); + retmem(line); + line = bigger_line; + if (fgetws(&line[line_index], line_size, fp) == NULL) + continue; + line_index = 2 * line_index; + line_size = 2 * line_size; + } + + colon = (wchar_t *) wschr(line, (int) colon_char); + if (colon == NULL) { + continue; + } + dollar = (wchar_t *) wschr(line, (int) dollar_char); + line[wslen(line) - 1] = (int) nul_char; + if (IS_WEQUALN(&colon[2], wcb, + (int) recursive_name->hash.length)) { + /* + * If this entry is an old entry, ignore it + */ + MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); + if (dollar == NULL || + !IS_WEQUALN(wcs_buffer, (dollar+1) - VER_LEN, VER_LEN)){ + continue; + } + rp = ALLOC(Recursive_make); + (void) memset((char *) rp, 0, sizeof (Recursive_make_rec)); + /* + * set conditional_macro_string if string is present + */ + rp->oldline = (wchar_t *) wsdup(line); + if ( dollar != NULL ){ + rp->cond_macrostring = + (wchar_t *) wsdup(dollar - VER_LEN + 1); + } + /* + * get target name into recursive struct + */ + *colon = (int) nul_char; + rp->target = (wchar_t *) wsdup(line); + *bpatch = rp; + bpatch = &rp->next; + } + } + (void) fclose(fp); +} + +/* + * report_recursive_dep(target, line) + * + * Report a target as recursive. + * + * Parameters: + * line Dependency line reported + * + * Static variables used: + * bpatch Points to slot where next cell should be added + * changed Written if report set changed + */ +void +report_recursive_dep(Name target, wchar_t *line) +{ + Recursive_make rp; + wchar_t rec_buf[STRING_BUFFER_LENGTH]; + String_rec string; + + INIT_STRING_FROM_STACK(string, rec_buf); + cond_macros_into_string(target, &string); + /* + * find an applicable recursive entry, if there isn't one, create it + */ + rp = find_recursive_target(target); + if (rp == NULL) { + rp = ALLOC(Recursive_make); + (void) memset((char *) rp, 0, sizeof (Recursive_make_rec)); + wchar_t * wcb = get_wstring(target->string_mb); // XXX Tolik: needs retmem + rp->target = wcb; + rp->newline = (wchar_t *) wsdup(line); + rp->cond_macrostring = (wchar_t *) wsdup(rec_buf); + *bpatch = rp; + bpatch = &rp->next; + changed = true; + } else { + if ((rp->oldline != NULL) && !IS_WEQUAL(rp->oldline, line)) { + rp->newline = (wchar_t *) wsdup(line); + changed = true; + } + rp->removed = false; + } +} + +/* + * find_recursive_target(target) + * + * Search the list for a given target. + * + * Return value: + * The target cell + * + * Parameters: + * target The target we need + * top_level_target more info used to determinde the + * target we need + * + * Static variables used: + * recursive_list The list of targets + */ +Recursive_make +find_recursive_target(Name target) +{ + Recursive_make rp; + String_rec string; + wchar_t rec_buf[STRING_BUFFER_LENGTH]; + + INIT_STRING_FROM_STACK(string, rec_buf); + cond_macros_into_string(target, &string); + + Wstring tstr(target); + wchar_t * wcb = tstr.get_string(); + for (rp = recursive_list; rp != NULL; rp = rp->next) { + /* + * If this entry has already been removed, ignore it. + */ + if (rp->removed) + continue; + /* + * If this target, and the target on the list are the same + * and if one of them contains conditional macro info, while + * the other doesn't, remove this entry from the list of + * recursive entries. This can only happen if the Makefile + * has changed to no longer contain conditional macros. + */ + if (IS_WEQUAL(rp->target, wcb)) { + if (rp->cond_macrostring[VER_LEN] == '\0' && + string.buffer.start[VER_LEN] != '\0'){ + rp->removed = true; + continue; + } else if (rp->cond_macrostring[VER_LEN] != '\0' && + string.buffer.start[VER_LEN] == '\0'){ + rp->removed = true; + continue; + } + } + /* + * If this is not a VERS2 entry, only need to match + * the target name. toptarg information from VERS1 entries + * are ignored. + */ + MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); + if (IS_WEQUALN(wcs_buffer, string.buffer.start, VER_LEN)) { + if (IS_WEQUAL(rp->cond_macrostring, + string.buffer.start) && + IS_WEQUAL(rp->target, wcb)) { + return rp; + } + } else { + if (IS_WEQUAL(rp->target, wcb)) { + return rp; + } + } + } + return NULL; +} + +/* + * remove_recursive_dep(target, top_level_target) + * + * Mark a target as no longer recursive. + * + * Parameters: + * target The target we want to remove + * top_level_target target we want to remove must be built from + * the same top level target + * + * Static variables used: + * changed Written if report set changed + */ +void +remove_recursive_dep(Name target) +{ + Recursive_make rp; + + rp = find_recursive_target(target); + + if ( rp != NULL ) { + rp->removed = true; + changed = true; + if(rp->target) { + retmem(rp->target); + rp->target = NULL; + } + if(rp->newline) { + retmem(rp->newline); + rp->newline = NULL; + } + if(rp->oldline) { + retmem(rp->oldline); + rp->oldline = NULL; + } + if(rp->cond_macrostring) { + retmem(rp->cond_macrostring); + rp->cond_macrostring = NULL; + } + } +} + +#ifdef NSE +/* + * report_recursive_done() + * + * Write the .nse_depinfo file. + * + * Parameters: + * + * Static variables used: + * recursive_list The list of targets + * changed Written if report set changed + * + * Global variables used: + * recursive_name The Name ".RECURSIVE", compared against + */ +void +report_recursive_done(void) +{ + char *search_dir; + char nse_depinfo[MAXPATHLEN]; + char tmpfile[MAXPATHLEN]; + FILE *ofp; + FILE *ifp; + wchar_t *space; + wchar_t *data; + wchar_t *line; + wchar_t *bigger_line; + int line_size, line_index; + int lock_err; + Recursive_make rp; + + if (changed == false) { + return; + } + + search_dir = getenv(NOCATGETS("NSE_DEP")); + if (search_dir == NULL) { + return; + } + (void) sprintf(nse_depinfo, "%s/%s", search_dir, NSE_DEPINFO); + (void) sprintf(tmpfile, "%s.%d", nse_depinfo, getpid()); + ofp = fopen(tmpfile, "w"); + if (ofp == NULL) { + (void) fprintf(stderr, + catgets(catd, 1, 116, "Cannot open `%s' for writing\n"), + tmpfile); + return; + } + (void) sprintf(nse_depinfo_lockfile, + "%s/%s", search_dir, NSE_DEPINFO_LOCK); + if (lock_err = file_lock(nse_depinfo, + nse_depinfo_lockfile, + (int *) &nse_depinfo_locked, 0)) { + (void) fprintf(stderr, + catgets(catd, 1, 117, "writing .RECURSIVE lines to %s\n"), + tmpfile); + (void) fprintf(stderr, + catgets(catd, 1, 118, "To recover, merge .nse_depinfo.%d with .nse_depinfo\n"), + getpid(), + catgets(catd, 1, 119, "with .nse_depinfo")); + } + + if (nse_depinfo_locked) { + ifp = fopen(nse_depinfo, "r"); + if (ifp != NULL) { + /* + * Copy all the non-.RECURSIVE lines from + * the old file to the new one. + */ + line_size = MAXPATHLEN; + line_index = line_size - 1; + line = ALLOC_WC(line_size); + while (fgetws(line, line_size, ifp) != NULL) { + while (wslen(line) == line_index) { + if (line[wslen(line) - 1] == '\n') { + continue; + } + bigger_line = ALLOC_WC(2 * line_size); + wscpy(bigger_line, line); + retmem(line); + line = bigger_line; + if (fgetws(&line[line_index], + line_size, ifp) == NULL) + continue; + line_index = 2 * line_index; + line_size = 2 * line_size; + } + + space = wschr(line, (int) space_char); + if (space != NULL && + IS_WEQUALN(&space[1], + recursive_name->string, + (int) recursive_name->hash.length)) { + continue; + } + WCSTOMBS(mbs_buffer, line); + (void) fprintf(ofp, "%s", mbs_buffer); + } + (void) fclose(ifp); + } + } + + /* + * Write out the .RECURSIVE lines. + */ + for (rp = recursive_list; rp != NULL; rp = rp->next) { + if (rp->removed) { + continue; + } + if (rp->newline != NULL) { + data = rp->newline; + } else { + data = rp->oldline; + } + if (data != NULL) { + WCSTOMBS(mbs_buffer, data); + (void) fprintf(ofp, "%s\n", mbs_buffer); + } + } + (void) fclose(ofp); + + if (nse_depinfo_locked) { + (void) rename(tmpfile, nse_depinfo); + (void) unlink(nse_depinfo_lockfile); + nse_depinfo_locked = false; + nse_depinfo_lockfile[0] = '\0'; + (void) chmod(nse_depinfo, 0666); + } +} +#endif // NSE + +/* gather_recursive_deps() + * + * Create or update list of recursive targets. + */ +void +gather_recursive_deps(void) +{ + Name_set::iterator np, e; + String_rec rec; + wchar_t rec_buf[STRING_BUFFER_LENGTH]; + register Property lines; + Boolean has_recursive; + Dependency dp; + + report_recursive_init(); + + /* Go thru all targets and dump recursive dependencies */ + for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) { + if (np->has_recursive_dependency){ + has_recursive = false; + /* + * start .RECURSIVE line with target: + */ + INIT_STRING_FROM_STACK(rec, rec_buf); + APPEND_NAME(np, &rec, FIND_LENGTH); + append_char((int) colon_char, &rec); + append_char((int) space_char, &rec); + + for (lines = get_prop(np->prop,recursive_prop); + lines != NULL; + lines = get_prop(lines->next, recursive_prop)) { + /* + * if entry is already in depinfo + * file or entry was not built, ignore it + */ + if (lines->body.recursive.in_depinfo) + continue; + if (!lines->body.recursive.has_built) + continue; + has_recursive = true; + lines->body.recursive.in_depinfo=true; + + /* + * Write the remainder of the + * .RECURSIVE line + */ + APPEND_NAME(recursive_name, &rec, + FIND_LENGTH); + append_char((int) space_char, &rec); + APPEND_NAME(lines->body.recursive.directory, + &rec, FIND_LENGTH); + append_char((int) space_char, &rec); + APPEND_NAME(lines->body.recursive.target, + &rec, FIND_LENGTH); + append_char((int) space_char, &rec); + + /* Complete list of makefiles used */ + for (dp = lines->body.recursive.makefiles; + dp != NULL; + dp = dp->next) { + APPEND_NAME(dp->name, &rec, FIND_LENGTH); + append_char((int) space_char, &rec); + } + } + /* + * dump list of conditional targets, + * and report recursive entry, if needed + */ + cond_macros_into_string(np, &rec); + if (has_recursive){ + report_recursive_dep(np, rec.buffer.start); + } + + } else if ( np->has_built ) { + remove_recursive_dep(np); + } + } +} + |