summaryrefslogtreecommitdiff
path: root/dmake/make.c
diff options
context:
space:
mode:
authorVladimir Glazounov <vg@openoffice.org>2007-01-18 08:30:56 +0000
committerVladimir Glazounov <vg@openoffice.org>2007-01-18 08:30:56 +0000
commit88f776d969af48361ce7faf28aea09e7f8421676 (patch)
treef7c4c25e96098dd98cbe59fbc21d2f065fef8a55 /dmake/make.c
parent4ed2a92b822e51d2599fcae7cbdccd9844f78b38 (diff)
INTEGRATION: CWS dmake47 (1.7.2); FILE MERGED
2006/11/19 05:27:24 vq 1.7.2.11: #i71704# Let the global .SEQUENTIAL attribute implicitely set MAXPROCESS=1 and disallow MAXPROCESS to be changed if the global .SEQUENTIAL is set. 2006/11/12 05:06:38 vq 1.7.2.10: #i71422# Add a new feature: Using @@ as a recipe prefix redirects the output (stdout and stderr) of a recipe to /dev/null (or NUL on W32) completely suppressing the output of that recipe to the terminal. As for the @ prefix this can be disabled using the -v[r] switch. 2006/11/09 22:33:22 vq 1.7.2.9: #i69821# Fix/improve $(TMD) handling. 2006/11/09 18:16:33 vq 1.7.2.8: #i69821# Add comment where TMD is detecting different drive letters for native W32 dmake versions. 2006/10/08 23:27:11 vq 1.7.2.7: #i70210# Fix dmakes handling of empty dynamic prerequisites. 2006/10/08 22:57:22 vq 1.7.2.6: #i70168# Remove FIXME. 2006/10/08 22:49:03 vq 1.7.2.5: #i70168# Improve $ handling in targets/prerequisites. 2006/10/06 04:02:35 vq 1.7.2.4: #i69742# Don't targets with $ in the filepath as dynamic macros. ($$ means a single $ in the filepath.) 2006/09/29 21:20:45 vq 1.7.2.3: #i69953# Remove NO_DRIVE_LETTERS, use HAVE_DRIVE_LETTERS instead. 2006/09/29 18:50:23 vq 1.7.2.2: #i69814# Add/fix option to make directory cache case insensitive. (Make this the default for Windows and Mac OS X.) Added testcase. 2006/09/28 21:42:38 vq 1.7.2.1: #i69821# Fix TMD macro and add testcase.
Diffstat (limited to 'dmake/make.c')
-rw-r--r--dmake/make.c262
1 files changed, 132 insertions, 130 deletions
diff --git a/dmake/make.c b/dmake/make.c
index ebca4a6713ad..77685aa6e5e2 100644
--- a/dmake/make.c
+++ b/dmake/make.c
@@ -1,6 +1,6 @@
/* $RCSfile: make.c,v $
--- $Revision: 1.7 $
--- last change: $Author: vg $ $Date: 2006-09-25 09:40:24 $
+-- $Revision: 1.8 $
+-- last change: $Author: vg $ $Date: 2007-01-18 09:30:56 $
--
-- SYNOPSIS
-- Perform the update of all outdated targets.
@@ -307,6 +307,8 @@ CELLPTR setdirroot;
for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
tcp = dp->cl_prq;
if( push ) {
+ /* If we changed the directory because of .SETDIR write Pwd into
+ * tcp->ce_dir so that it holds an absolute path. */
if( !(tcp->ce_attr & A_POOL) && tcp->ce_dir ) FREE( tcp->ce_dir );
tcp->ce_dir = _pool_lookup(Pwd);
tcp->ce_attr |= A_SETDIR|A_POOL;
@@ -320,7 +322,7 @@ CELLPTR setdirroot;
time_t itime = cp->ce_time;
if (cp->ce_parent && (cp->ce_parent->ce_flag & F_MULTI)) {
- /* Inherit the stat info from the parent. */
+ /* Inherit the stat info from the F_MULTI parent. */
cp->ce_time = cp->ce_parent->ce_time;
cp->ce_flag |= F_STAT;
/* Propagate the A_PRECIOUS attribute from the parent. */
@@ -329,7 +331,8 @@ CELLPTR setdirroot;
else {
for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
tcp = dp->cl_prq;
- Stat_target( tcp, TRUE, FALSE );
+ /* Check if target already exists. */
+ Stat_target( tcp, 1, FALSE );
if( tcp->ce_time == (time_t)0L ) {
if( tcp->ce_flag & F_INFER )
@@ -412,7 +415,6 @@ CELLPTR setdirroot;
/* First round, will be repeated a second time below. */
for( prev=NULL,dp=cp->ce_prq; dp != NIL(LINK); prev=dp, dp=next ) {
int seq;
- int nesting_count;
/* This is the only macro that needs to be reset while building
* prerequisites since it is set when we make each prerequisite. */
@@ -443,27 +445,30 @@ CELLPTR setdirroot;
tcp = dp->cl_prq;
}
+ /* If the previous target (prereq) is not yet ready return if
+ * seq is TRUE. */
if( seq && !made ) goto stop_making_it;
- nesting_count = 0;
- while ( tcp
- && strchr(tcp->CE_NAME, '$')
- ) {
- if ( nesting_count++ > DynamicNestLevel ) {
- Fatal( "Dynamic Macro nesting level exceeded [%s]",
- cp->CE_NAME );
- }
- /* Make this prerequisite link point at the real prerequisite we
- * are after, ie figure out what the dynamic one is and point at it.*/
+ /* Expand dynamic prerequisites. The F_MARK flag is guarging against
+ * possible double expandion of dynamic prerequisites containing more
+ * than one prerequisite. */
+ /* A new A_DYNAMIC attribute could save a lot of strchr( ,'$') calls. */
+ if ( tcp && !(tcp->ce_flag & F_MARK) && strchr(tcp->CE_NAME, '$') ) {
+ /* Replace this dynamic prerequisite with the the real prerequisite,
+ * and add the additional prerequisites if there are more than one.*/
name = Expand( tcp->CE_NAME );
if( strcmp(name,cp->CE_NAME) == 0 )
Fatal("Detected circular dynamic dependency; generated '%s'",name);
- /* Call helper for dynamic prerequisite expansion. */
+ /* Call helper for dynamic prerequisite expansion to replace the
+ * prerequisite with the expanded version and add the new
+ * prerequisites, if the macro expanded to more than one, after
+ * the current list element. */
dp = _expand_dynamic_prq( cp->ce_prq, dp, name );
FREE( name );
+ /* _expand_dynamic_prq() probably changed dp->cl_prq. */
tcp = dp->cl_prq;
if ( tcp ) {
next = dp->cl_next;
@@ -471,8 +476,8 @@ CELLPTR setdirroot;
}
/* Dynamic expansion results in a NULL cell only when the the new
- * prerequisite is already in the prerequisite list. In this case
- * delete the cell and continue. */
+ * prerequisite is already in the prerequisite list or empty. In this
+ * case delete the cell and continue. */
if ( tcp == NIL(CELL) ) {
FREE(dp);
if ( prev == NIL(LINK) ) {
@@ -486,6 +491,9 @@ CELLPTR setdirroot;
continue;
}
+ /* Clear F_MARK flag that could have been set by _expand_dynamic_prq(). */
+ tcp->ce_attr &= ~(F_MARK);
+
if( cp->ce_attr & A_LIBRARY ) {
tcp->ce_attr |= A_LIBRARYM;
tcp->ce_lib = cp->ce_fname;
@@ -511,10 +519,13 @@ CELLPTR setdirroot;
if( cp->ce_attr & A_LIBRARY )
tcp->ce_attr ^= A_LIBRARYM;
+ /* Return on error or if Make() is still running and A_SEQ is set. */
if( rval == -1 || (seq && (rval==1)) )
goto stop_making_it;
if( tcp->ce_time > ttime ) ttime = tcp->ce_time;
+
+ /* If tcp is ready, set made = F_MADE. */
made &= tcp->ce_flag & F_MADE;
}
@@ -712,6 +723,7 @@ CELLPTR setdirroot;
* of the target. */
if( push ) {
char *dir = nsetdirroot ? nsetdirroot->ce_dir : Makedir;
+ /* get relative path from current SETDIR to new SETDIR. */
char *pref = _prefix(dir,tcp->ce_dir);
char *nname = Build_path(pref, tcp->ce_fname);
@@ -769,42 +781,104 @@ stop_making_it:
static char *
-_prefix( pfx, pat )
+_prefix( pfx, pat )/*
+=====================
+ Return the relative path from pfx to pat. Both paths have to be absolute
+ paths. If the paths are on different resources or drives (if applicable)
+ return pat. */
char *pfx;
char *pat;
{
char *cmp1=pfx;
char *cmp2=pat;
- char *result = DmStrDup("");
+ char *result;
char *up;
+ int first = 1;
+#ifdef HAVE_DRIVE_LETTERS
+ int pfxdl = 0;
+ int patdl = 0;
+#endif
+
+ /* Micro optimization return immediately if pfx and pat are equal. */
+ if( strcmp(pfx, pat) == 0 )
+ return(DmStrDup(""));
+
+#ifdef HAVE_DRIVE_LETTERS
+ /* remove the drive letters to avoid getting them into the relative
+ * path later. */
+ if( *pfx && pfx[1] == ':' && isalpha(*pfx) ) {
+ pfxdl = 1;
+ cmp1 = DmStrSpn(pfx+2, DirBrkStr);
+ }
+ if( *pat && pat[1] == ':' && isalpha(*pat) ) {
+ patdl = 1;
+ cmp2 = DmStrSpn(pat+2, DirBrkStr);
+ }
+ /* If the drive letters are different use the abs. path. */
+ if( pfxdl && patdl && (tolower(*pfx) != tolower(*pat)) )
+ return(DmStrDup(pat));
+
+ /* If only one has a drive letter also use the abs. path. */
+ if( pfxdl != patdl )
+ return(DmStrDup(pat));
+
+ /* Continue without the drive letters. (Either none was present,
+ * or both were the same. This also solves the problem that the
+ * case of the drive letters sometimes depends on the shell.
+ * (cmd.exe vs. cygwin bash) */
+ pfx = cmp1;
+ pat = cmp2;
+#endif
+ /* Cut off equal leading parts of pfx, pat. Both have to be abs. paths. */
while(*pfx && *pat) {
+ /* skip leading dir. separators. */
pfx = DmStrSpn(cmp1, DirBrkStr);
pat = DmStrSpn(cmp2, DirBrkStr);
+ /* Only check in the first run of the loop. Leading slashes can only
+ * mean POSIX paths or Windows resources (two) slashes. Drive letters
+ * have no leading slash. In any case, if the number of slashes are
+ * not equal there can be no relative path from one two the other.
+ * In this case return the absolute path. */
+ if( first ) {
+ if( cmp1-pfx != cmp2-pat ) {
+ return(DmStrDup(pat));
+ }
+ first = 0;
+ }
+
+ /* find next dir. separator (or ""). */
cmp1 = DmStrPbrk(pfx, DirBrkStr);
cmp2 = DmStrPbrk(pat, DirBrkStr);
+ /* if length of directory name is equal compare the strings. If equal
+ * go into next loop. */
if ( (cmp1-pfx) != (cmp2-pat) || strncmp(pfx,pat,cmp1-pfx) != 0 )
break;
}
+ result = DmStrDup("");
up = DmStrJoin("..",DirSepStr,-1,FALSE);
cmp1 = pfx;
+ /* Add "../" for each directory in pfx */
while ( *(pfx=DmStrSpn(cmp1,DirBrkStr)) != '\0' ) {
cmp1 = DmStrPbrk(pfx,DirBrkStr);
result = DmStrJoin(result,up,-1,TRUE);
}
- cmp2 = pat;
- while ( *(pat=DmStrSpn(cmp2,DirBrkStr)) != '\0' ) {
- char *tmp;
- char *x;
- cmp2 = DmStrPbrk(pat, DirBrkStr);
- tmp = DmStrDup(Build_path(result,x=DmSubStr(pat,cmp2)));
+ pat = DmStrSpn(pat,DirBrkStr);
+ /* Append pat to result. */
+ if( *pat != '\0' ) {
+ cmp2 = DmStrDup(Build_path(result, pat));
FREE(result);
- FREE(x);
- result = tmp;
+ result = cmp2;
+ } else {
+ /* if pat is empty and result exists remove the trailing slash
+ * from the last "../". */
+ if( *result ) {
+ result[strlen(result)-1] = '\0';
+ }
}
return(result);
@@ -833,23 +907,33 @@ _expand_dynamic_prq( head, lp, name )/*
=======================================
The string name can contain one or more target names. Check if these are
already a prerequisite for the current target. If not add them to the list
- of prerequisites. If no prerequisites were added set lp->cl_prq to NULL. */
+ of prerequisites. If no prerequisites were added set lp->cl_prq to NULL.
+ Set the F_MARK flag to indicate that the prerequisite was expanded.
+ Use cl_flag instead?? */
LINKPTR head;
LINKPTR lp;
char *name;
{
CELLPTR cur = lp->cl_prq;
- /* If condition is true, no space is found. */
- if ( strchr(name, ' ') == NIL(char) ) {
- CELLPTR prq = Def_cell(name);
+ if( !(*name) ) {
+ /* If name is empty this leaves lp->cl_prq unchanged -> No prerequisite added. */
+ ;
+ }
+ else if ( strchr(name, ' ') == NIL(char) ) {
+ /* If condition above is true, no space is found. */
+ CELLPTR prq = Def_cell(name);
LINKPTR tmp;
+ /* Check if prq already exists. */
for(tmp=head;tmp != NIL(LINK) && tmp->cl_prq != prq;tmp=tmp->cl_next);
/* If tmp is NULL then the prerequisite is new and is added to the list. */
- if ( !tmp )
+ if ( !tmp ) {
+ /* replace the prerequisite with the expanded version. */
lp->cl_prq = prq;
+ lp->cl_prq->ce_flag |= F_MARK;
+ }
}
else {
LINKPTR tlp = lp;
@@ -869,7 +953,8 @@ char *name;
/* If tmp is not NULL the prerequisite already exists. */
if ( tmp ) continue;
- /* Add list elements when more then one new prerequisite is found. */
+ /* Add list elements behind the first if more then one new
+ * prerequisite is found. */
if ( first ) {
first = FALSE;
}
@@ -881,6 +966,7 @@ char *name;
}
tlp->cl_prq = prq;
+ tlp->cl_prq->ce_flag |= F_MARK;
}
CLEAR_TOKEN( &token );
}
@@ -891,6 +977,7 @@ char *name;
lp->cl_flag = 0;
}
+ /* Is returned unchanged. */
return(lp);
}
@@ -1145,7 +1232,7 @@ CELLPTR cp;
/* Print command and remove continuation sequence from cmnd. */
Print_cmnd(cmnd, !(do_it && (l_attr & A_SILENT)), 0);
}
- rval=Do_cmnd(cmnd,FALSE,do_it,cp,(l_attr&A_IGNORE)!=0, shell,
+ rval=Do_cmnd(cmnd,FALSE,do_it,cp,l_attr,
rp->st_next == NIL(STRING) );
}
}
@@ -1167,8 +1254,7 @@ CELLPTR cp;
chmod(groupfile,0700);
#endif
}
- rval = Do_cmnd(groupfile, TRUE, do_it, cp, (attr & A_IGNORE)!=0,
- TRUE, TRUE);
+ rval = Do_cmnd(groupfile, TRUE, do_it, cp, attr | A_SHELL, TRUE);
}
_recipes[ RP_RECIPE ] = orp;
@@ -1327,103 +1413,19 @@ int ignore;
static void
_set_tmd()/*
============
- Set the TMD Macro */
+ Set the TMD Macro. This is the path from the present directory (value of
+ $(PWD)) to the directory dmake was started up in (value of $(MAKEDIR)).
+*/
{
- char *m, *p;
- char *mend, *pend;
- char *mtd, *ptd;
- int mleadslash, pleadslash;
char *tmd;
- int first = 1;
-
- /* Don't use Get_token because this fails on paths that contain spaces. */
- m = DmStrSpn(Makedir, DirBrkStr);
- mleadslash = m - Makedir;
- p = DmStrSpn(Pwd, DirBrkStr);
- pleadslash = p - Pwd;
-
- /* leading slashes can only mean POSIX paths or Windows resources (two)
- * slashes. In any case if the number of slashes are not equal there
- * can be no relative path from one two the other. Use the Makedir path. */
- if(mleadslash != pleadslash) {
- tmd = Makedir;
- goto tmd_end;
- }
- /* If Makedir and Pwd are identical skip to the end. */
- for(mend=m, pend=p; *mend && *pend && *mend==*pend; mend++, pend++)
- ;
- if( ( ! *mend ) && ( ! *pend ) ) {
- tmd = DmStrDup( "." );
- goto tmd_end;
+ tmd = _prefix(Pwd, Makedir);
+ if( *tmd ) {
+ Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
+ } else {
+ Def_macro( "TMD", ".", M_MULTI | M_EXPANDED );
}
-
- /* If Makedir and Pwd are not identical we will construct TMD. */
- tmd = DmStrDup( "" );
-
- do {
-
- /* get the next top directory name */
- mend = DmStrPbrk( m, DirBrkStr );
- /* For DOSish filenames the first part might be a drive letter */
-#if !defined(NO_DRIVE_LETTERS)
- if( first && *mend == ':' )
- mend++;
-#endif
-
- mtd = DmSubStr( m, mend ); /* Free later */
- /* {m|p}end either points to a DirBrkStr member or the end of string. */
- if(*mend) mend++;
- m = mend;
-
- pend = DmStrPbrk( p, DirBrkStr );
-#if !defined(NO_DRIVE_LETTERS)
- if( first && *pend == ':' )
- pend++;
-#endif
-
- ptd = DmSubStr( p, pend ); /* Free later */
- if(*pend) pend++;
- p = pend;
-
- if( strcmp(mtd, ptd) ) { /* they differ */
- char *tmp = 0;
-
- if( first ) { /* They differ in the first component */
- FREE( tmd );
- FREE( mtd );
- FREE( ptd );
- tmd = Makedir; /* In this case use the full path */
- break;
- }
-
- if( *ptd ) {
- /* Build_path puts a DirSepStr behind the first parameter if
- * its length is greater null, even if the second parameter
- * is empty. */
- if(*tmd)
- tmp = Build_path( "..", tmd );
- else
- tmp = "..";
- FREE( tmd );
- tmd = DmStrDup( tmp );
- }
- if( *mtd ) {
- tmp = Build_path( tmd, mtd );
- FREE( tmd );
- tmd = DmStrDup( tmp );
- }
- }
-
- FREE( mtd );
- FREE( ptd );
- first = 0;
- } while (*m || *p);
-
-tmd_end:
-
- Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
- if( tmd != Makedir ) FREE( tmd );
+ FREE( tmd );
}