summaryrefslogtreecommitdiff
path: root/usr/src/make_src/Make/bin/make/common/rep.cc
diff options
context:
space:
mode:
authorIgor Pashev <igor.pashev@nexenta.com>2012-06-29 14:36:07 +0400
committerIgor Pashev <igor.pashev@nexenta.com>2012-06-29 14:36:07 +0400
commite0463df9c3d2ee6155221cc443c571d5da47098a (patch)
tree5c6b99e64c1b65d986e2722728c74f202a578be6 /usr/src/make_src/Make/bin/make/common/rep.cc
downloadsunmake-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.cc529
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);
+ }
+ }
+}
+