From b24c11f89613f6d9ed3429e642b0c4bd610efd7e Mon Sep 17 00:00:00 2001 From: "Matthias Huetsch [mhu]" Date: Thu, 25 Nov 2010 14:13:43 +0100 Subject: #i115784# dmake: fix memory errors uncovered by valgrind and other tools. --- dmake/config.h.in | 3 + dmake/configure | 2 +- dmake/configure.in | 2 +- dmake/dmake.c | 50 ++-- dmake/expand.c | 668 +++++++++++++++++++++---------------------- dmake/function.c | 68 ++--- dmake/infer.c | 389 ++++++++++++------------- dmake/parse.c | 204 +++++++------- dmake/rulparse.c | 779 +++++++++++++++++++++++++-------------------------- dmake/sysintf.c | 22 +- dmake/unix/runargv.c | 171 ++++++----- 11 files changed, 1186 insertions(+), 1172 deletions(-) (limited to 'dmake') diff --git a/dmake/config.h.in b/dmake/config.h.in index c8aa63a861b9..ed639aa99b03 100644 --- a/dmake/config.h.in +++ b/dmake/config.h.in @@ -55,6 +55,9 @@ /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + /* Define to 1 if you have the `settz' function. */ #undef HAVE_SETTZ diff --git a/dmake/configure b/dmake/configure index f8a1bd822914..7e6d05ab8a65 100755 --- a/dmake/configure +++ b/dmake/configure @@ -7437,7 +7437,7 @@ done -for ac_func in getcwd getwd strerror setvbuf tzset settz mkstemp tempnam gettimeofday +for ac_func in getcwd getwd strerror setvbuf tzset settz mkstemp tempnam gettimeofday setenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/dmake/configure.in b/dmake/configure.in index 498c7b2372de..c903d94faab8 100755 --- a/dmake/configure.in +++ b/dmake/configure.in @@ -211,7 +211,7 @@ AC_FUNC_MEMCMP AC_TYPE_SIGNAL AC_FUNC_UTIME_NULL AC_FUNC_VPRINTF -AC_CHECK_FUNCS(getcwd getwd strerror setvbuf tzset settz mkstemp tempnam gettimeofday) +AC_CHECK_FUNCS(getcwd getwd strerror setvbuf tzset settz mkstemp tempnam gettimeofday setenv) # Usefull, but special to newlib/MSVC AC_CHECK_FUNCS(strlwr) diff --git a/dmake/dmake.c b/dmake/dmake.c index b96bf4ce3146..ddfe3a88ad06 100644 --- a/dmake/dmake.c +++ b/dmake/dmake.c @@ -380,16 +380,19 @@ char **argv; _warn = TRUE; /* If -r was not given find and parse startup-makefile. */ - if( Rules ) { - char *fname; - - /* Search_file() also checks the environment variable. */ - if( (mkfil=Search_file("MAKESTARTUP", &fname)) != NIL(FILE) ) { - Parse(mkfil); - Def_macro( "MAKESTARTUP", fname, M_EXPANDED|M_MULTI|M_FORCE ); - } - else - Fatal( "Configuration file `%s' not found", fname ); + if( Rules ) + { + char *fname = NIL(char); + + /* Search_file() also checks the environment variable. */ + if( (mkfil=Search_file("MAKESTARTUP", &fname)) != NIL(FILE) ) + { + Parse(mkfil); + Def_macro( "MAKESTARTUP", fname, M_EXPANDED|M_MULTI|M_FORCE ); + } + else + Fatal( "Configuration file `%s' not found", fname ); + if ( fname != NIL(char)) { FREE( fname ); fname = NIL(char); } } /* Define the targets set on the command line now. */ @@ -428,8 +431,7 @@ char **argv; char *p; if( strcmp(f, "stdin") == 0 ) f = "-"; - p = DmStrAdd( "-f", f, FALSE ); - Def_macro( "MAKEFILE", p, M_PRECIOUS|M_NOEXPORT ); + Def_macro( "MAKEFILE", p = DmStrAdd( "-f", f, FALSE ), M_PRECIOUS|M_NOEXPORT ); FREE(p); Parse( mkfil ); } else if( !Rules ) @@ -663,23 +665,25 @@ char **rname; */ if( (hp = GET_MACRO(macname)) != NIL(HASH) ) { - /* Only expand if needed. */ - if( hp->ht_flag & M_EXPANDED ) { - ename = fname = DmStrDup(hp->ht_value); - } else { - ename = fname = Expand(hp->ht_value); - } + /* Only expand if needed. */ + if( hp->ht_flag & M_EXPANDED ) { + ename = fname = DmStrDup(hp->ht_value); + } else { + ename = fname = Expand(hp->ht_value); + } - if( hp->ht_flag & M_PRECIOUS ) fil = Openfile(fname, FALSE, FALSE); + if( hp->ht_flag & M_PRECIOUS ) fil = Openfile(fname, FALSE, FALSE); } if( fil == NIL(FILE) ) { - fname=Expand(Read_env_string(macname)); - if( (fil = Openfile(fname, FALSE, FALSE)) != NIL(FILE) ) FREE(ename); + fname=Expand(Read_env_string(macname)); + if( (fil = Openfile(fname, FALSE, FALSE)) != NIL(FILE) ) FREE(ename); } - if( fil == NIL(FILE) && hp != NIL(HASH) ) - fil = Openfile(fname=ename, FALSE, FALSE); + if( fil == NIL(FILE) && hp != NIL(HASH) ) { + if ( fname != NIL(char) ) { FREE(fname); fname = NIL(char); } + fil = Openfile(fname=ename, FALSE, FALSE); + } if( rname ) *rname = fname; diff --git a/dmake/expand.c b/dmake/expand.c index b7232303177e..50bbbdc46760 100644 --- a/dmake/expand.c +++ b/dmake/expand.c @@ -133,23 +133,23 @@ char *src; /* pointer to source string */ /* START <+...+> KLUDGE */ if( (ks=DmStrStr(start,"<+")) != NIL(char) - && (ke=DmStrStr(ks,"+>")) != NIL(char) ){ - char *t1, *t2; - - res = DmStrJoin( res, t2=Expand(t1=DmSubStr(start,ks)), -1, TRUE); - FREE(t1); FREE(t2); - - t1 = DmSubStr(ks+2, ke+1); t1[ke-ks-2] = ')'; - t2 = DmStrJoin( "$(mktmp ", t1, -1,FALSE); - FREE(t1); - res = DmStrJoin( res, t2=Expand(t2), -1, TRUE); - FREE(t2); - src = ke+2; + && (ke=DmStrStr(ks,"+>")) != NIL(char) ) { + char *t1, *t2; + + res = DmStrJoin( res, t2=Expand(t1=DmSubStr(start,ks)), -1, TRUE); + FREE(t1); FREE(t2); + + t1 = DmSubStr(ks+2, ke+1); t1[ke-ks-2] = ')'; + t2 = DmStrJoin( "$(mktmp ", t1, -1,FALSE); + FREE(t1); + res = DmStrJoin( res, t1=Expand(t2), -1, TRUE); + FREE(t1); FREE(t2); + src = ke+2; } /* END <+...+> KLUDGE */ else { - res = DmStrJoin( res, tmp = ScanToken(start,&src,TRUE), -1, TRUE ); - FREE( tmp ); + res = DmStrJoin( res, tmp = ScanToken(start,&src,TRUE), -1, TRUE ); + FREE( tmp ); } } @@ -726,36 +726,36 @@ int doexpand; /* If TRUE enables macro expansion */ break; case '\\': /* Transform \ -> ' '. */ - if( s[1] != '\n' ) { - done = !lev; - break; - } else { - size_t len; - s[1] = ' '; - len = strlen(s+1)+1; - memmove( s, s+1, len ); - } - /*FALLTHRU*/ + if( s[1] != '\n' ) { + done = !lev; + break; + } else { + size_t len; + s[1] = ' '; + len = strlen(s+1)+1; + memmove( s, s+1, len ); + } + /*FALLTHRU*/ case ' ': case '\t': if ( lev == 1 ) fflag = 1; break; case '\0': /* check for null */ - *ps = s; - done = TRUE; - if( lev ) { /* catch $( or ${ without closing bracket */ - Fatal( "Syntax error in macro [$%s]. The closing bracket [%c] is missing.\n", start, edelim ); - } else - Fatal( "DEBUG: This cannot occur! [%s].\n", start ); - break; - - case ')': /* close macro brace */ - case '}': + *ps = s; + done = TRUE; + if( lev ) { /* catch $( or ${ without closing bracket */ + Fatal( "Syntax error in macro [$%s]. The closing bracket [%c] is missing.\n", start, edelim ); + } else + Fatal( "DEBUG: This cannot occur! [%s].\n", start ); + break; + + case ')': /* close macro brace */ + case '}': if( !lev ) /* A closing bracket without an .. */ - Fatal("Syntax error in macro [$%s]. Closing bracket [%c] cannot be a macro name.\n", start, *s ); + Fatal("Syntax error in macro [$%s]. Closing bracket [%c] cannot be a macro name.\n", start, *s ); else if( *s == edelim ) --lev; - /*FALLTHRU*/ + /*FALLTHRU*/ default: /* Done when lev == 0. This means either no */ done = !lev; /* opening bracket (single letter macro) or */ @@ -768,14 +768,14 @@ int doexpand; /* If TRUE enables macro expansion */ /* Check if this is a $A type macro. If so then we have to * handle it a little differently. */ if( bflag ) - macro_name = DmSubStr( start+1, s-1 ); + macro_name = DmSubStr( start+1, s-1 ); else - macro_name = DmSubStr( start, s ); + macro_name = DmSubStr( start, s ); /* If we don't have to expand the macro we're done. */ if (!doexpand) { - *ps = s; - DB_RETURN(macro_name); + *ps = s; + DB_RETURN(macro_name); } /* Check to see if the macro name contains spaces, if so then treat it @@ -783,251 +783,251 @@ int doexpand; /* If TRUE enables macro expansion */ * deal with it. We do not call the function expander if the function * invocation begins with a '$' */ if( fflag && *macro_name != '$' ) { - result = Exec_function(macro_name); + result = Exec_function(macro_name); } else { - /* Check if the macro is a recursive macro name, if so then - * EXPAND the name before expanding the value */ - if( strchr( macro_name, '$' ) != NIL(char) ) { - recurse_name = Expand( macro_name ); - FREE( macro_name ); - macro_name = recurse_name; - } + /* Check if the macro is a recursive macro name, if so then + * EXPAND the name before expanding the value */ + if( strchr( macro_name, '$' ) != NIL(char) ) { + recurse_name = Expand( macro_name ); + FREE( macro_name ); + macro_name = recurse_name; + } - /* Code to do value expansion goes here, NOTE: macros whose assign bit - is one have been evaluated and assigned, they contain no further - expansions and thus do not need their values expanded again. */ + /* Code to do value expansion goes here, NOTE: macros whose assign bit + is one have been evaluated and assigned, they contain no further + expansions and thus do not need their values expanded again. */ - if( (hp = GET_MACRO( macro_name )) != NIL(HASH) ) { - if( hp->ht_flag & M_MARK ) - Fatal( "Detected circular macro [%s]", hp->ht_name ); + if( (hp = GET_MACRO( macro_name )) != NIL(HASH) ) { + if( hp->ht_flag & M_MARK ) + Fatal( "Detected circular macro [%s]", hp->ht_name ); - if( !(hp->ht_flag & M_EXPANDED) ) { - hp->ht_flag |= M_MARK; - result = Expand( hp->ht_value ); - hp->ht_flag ^= M_MARK; - } - else if( hp->ht_value != NIL(char) ) - result = DmStrDup( hp->ht_value ); - else - result = DmStrDup( "" ); + if( !(hp->ht_flag & M_EXPANDED) ) { + hp->ht_flag |= M_MARK; + result = Expand( hp->ht_value ); + hp->ht_flag ^= M_MARK; + } + else if( hp->ht_value != NIL(char) ) + result = DmStrDup( hp->ht_value ); + else + result = DmStrDup( "" ); - } - else { - /* The use of an undefined macro implicitly defines it but - * leaves its value to NIL(char). */ - hp = Def_macro( macro_name, NIL(char), M_EXPANDED ); - /* Setting M_INIT assures that this macro is treated unset like - * default internal macros. (Necessary for *= and *:=) */ - hp->ht_flag |= M_INIT; - - result = DmStrDup( "" ); - } - /* Mark macros as used only if we are not expanding them for - * the purpose of a .IF test, so we can warn about redef after use*/ - if( !If_expand ) hp->ht_flag |= M_USED; + } + else { + /* The use of an undefined macro implicitly defines it but + * leaves its value to NIL(char). */ + hp = Def_macro( macro_name, NIL(char), M_EXPANDED ); + /* Setting M_INIT assures that this macro is treated unset like + * default internal macros. (Necessary for *= and *:=) */ + hp->ht_flag |= M_INIT; + + result = DmStrDup( "" ); + } + /* Mark macros as used only if we are not expanding them for + * the purpose of a .IF test, so we can warn about redef after use*/ + if( !If_expand ) hp->ht_flag |= M_USED; } if( mflag ) { - char separator; - int modifier_list = 0; - int aug_mod = FALSE; - char *pat1; - char *pat2; - char *p; - - /* We are inside of a macro expansion. The "build up macro name, - * find its while loop above should have caught all \ and - * converted them to a real space. Let's verify this. */ - for( p=s; *p && *p != edelim && *p; p++ ) { - if( p[0] == '\\' && p[1] == '\n' ) { - size_t len; - p[1] = ' '; - len = strlen(p+1)+1; - memmove( p, p+1, len ); - } - } - if( !*p ) - Fatal( "Syntax error in macro modifier pattern [$%s]. The closing bracket [%c] is missing.\n", start, edelim ); - - /* Yet another brain damaged AUGMAKE kludge. We should accept the - * AUGMAKE bullshit of $(f:pat=sub) form of macro expansion. In - * order to do this we will forgo the normal processing if the - * AUGMAKE solution pans out, otherwise we will try to process the - * modifiers ala dmake. - * - * So we look for = in modifier string. - * If found we process it and not do the normal stuff */ - - for( p=s; *p && *p != '=' && *p != edelim; p++ ); - - if( *p == '=' ) { - char *tmp; - - pat1 = Expand(tmp = DmSubStr(s,p)); FREE(tmp); - s = p+1; - p = _scan_ballanced_parens(s+1, edelim); - - if ( !*p ) { - Fatal( "Incomplete macro expression [%s]", s ); - p = s+1; + char separator; + int modifier_list = 0; + int aug_mod = FALSE; + char *pat1; + char *pat2; + char *p; + + /* We are inside of a macro expansion. The "build up macro name, + * find its while loop above should have caught all \ and + * converted them to a real space. Let's verify this. */ + for( p=s; *p && *p != edelim && *p; p++ ) { + if( p[0] == '\\' && p[1] == '\n' ) { + size_t len; + p[1] = ' '; + len = strlen(p+1)+1; + memmove( p, p+1, len ); + } + } + if( !*p ) + Fatal( "Syntax error in macro modifier pattern [$%s]. The closing bracket [%c] is missing.\n", start, edelim ); + + /* Yet another brain damaged AUGMAKE kludge. We should accept the + * AUGMAKE bullshit of $(f:pat=sub) form of macro expansion. In + * order to do this we will forgo the normal processing if the + * AUGMAKE solution pans out, otherwise we will try to process the + * modifiers ala dmake. + * + * So we look for = in modifier string. + * If found we process it and not do the normal stuff */ + + for( p=s; *p && *p != '=' && *p != edelim; p++ ); + + if( *p == '=' ) { + char *tmp; + + pat1 = Expand(tmp = DmSubStr(s,p)); FREE(tmp); + s = p+1; + p = _scan_ballanced_parens(s+1, edelim); + + if ( !*p ) { + Fatal( "Incomplete macro expression [%s]", s ); + p = s+1; + } + pat2 = Expand(tmp = DmSubStr(s,p)); FREE(tmp); + + result = Apply_edit( result, pat1, pat2, TRUE, TRUE ); + FREE( pat1 ); + FREE( pat2 ); + s = p; + aug_mod = TRUE; } - pat2 = Expand(tmp = DmSubStr(s,p)); FREE(tmp); - - result = Apply_edit( result, pat1, pat2, TRUE, TRUE ); - FREE( pat1 ); - FREE( pat2 ); - s = p; - aug_mod = TRUE; - } - if( !aug_mod ) - while( *s && *s != edelim ) { /* while not at end of macro */ - char switch_char; + if( !aug_mod ) + while( *s && *s != edelim ) { /* while not at end of macro */ + char switch_char; - switch( switch_char = *s++ ) { - case '1': modifier_list |= JUST_FIRST_FLAG; break; + switch( switch_char = *s++ ) { + case '1': modifier_list |= JUST_FIRST_FLAG; break; - case 'b': - case 'B': modifier_list |= FILE_FLAG; break; + case 'b': + case 'B': modifier_list |= FILE_FLAG; break; - case 'd': - case 'D': modifier_list |= DIRECTORY_FLAG; break; + case 'd': + case 'D': modifier_list |= DIRECTORY_FLAG; break; - case 'f': - case 'F': modifier_list |= FILE_FLAG | SUFFIX_FLAG; break; + case 'f': + case 'F': modifier_list |= FILE_FLAG | SUFFIX_FLAG; break; - case 'e': - case 'E': modifier_list |= SUFFIX_FLAG; break; + case 'e': + case 'E': modifier_list |= SUFFIX_FLAG; break; - case 'l': - case 'L': modifier_list |= TOLOWER_FLAG; break; + case 'l': + case 'L': modifier_list |= TOLOWER_FLAG; break; - case 'i': - case 'I': modifier_list |= INFNAME_FLAG; break; + case 'i': + case 'I': modifier_list |= INFNAME_FLAG; break; - case 'u': - case 'U': modifier_list |= TOUPPER_FLAG; break; + case 'u': + case 'U': modifier_list |= TOUPPER_FLAG; break; - case 'm': - case 'M': - if( modifier_list || ( (*s != edelim) && (*s != ':') ) ) { + case 'm': + case 'M': + if( modifier_list || ( (*s != edelim) && (*s != ':') ) ) { Warning( "Map escape modifier must appear alone, ignored"); modifier_list = 0; - } - else { + } + else { /* map the escape codes in the separator string first */ for(p=result; (p = strchr(p,ESCAPE_CHAR)) != NIL(char); p++) - Map_esc( p ); - } - /* find the end of the macro spec, or the start of a new - * modifier list for further processing of the result */ + Map_esc( p ); + } + /* find the end of the macro spec, or the start of a new + * modifier list for further processing of the result */ - for( ; (*s != edelim) && (*s != ':') && *s; s++ ); - if( !*s ) - Fatal( "Syntax error in macro. [$%s].\n", start ); - if( *s == ':' ) s++; - break; + for( ; (*s != edelim) && (*s != ':') && *s; s++ ); + if( !*s ) + Fatal( "Syntax error in macro. [$%s].\n", start ); + if( *s == ':' ) s++; + break; - case 'n': - case 'N': modifier_list |= NORMPATH_FLAG; break; + case 'n': + case 'N': modifier_list |= NORMPATH_FLAG; break; - case 'S': - case 's': - if( modifier_list ) { + case 'S': + case 's': + if( modifier_list ) { Warning( "Edit modifier must appear alone, ignored"); modifier_list = 0; - } - else { + } + else { separator = *s++; for( p=s; *p != separator && *p; p++ ); if( !*p ) - Fatal( "Syntax error in subst macro. [$%s].\n", start ); + Fatal( "Syntax error in subst macro. [$%s].\n", start ); else { - char *t1, *t2; - pat1 = DmSubStr( s, p ); - for(s=p=p+1; (*p != separator) && *p; p++ ); - /* Before the parsing fixes in iz36027 the :s macro modifier - * erroneously worked with patterns with missing pattern - * separator, i.e. $(XXX:s#pat#sub). This is an error because - * it prohibits the use of following macro modifiers. - * I.e. $(XXX:s#pat#sub:u) falsely replaces with "sub:u". - * ??? Remove this special case once OOo compiles without - * any of this warnings. */ - if( !*p ) { - if( *(p-1) == edelim ) { - p--; - Warning( "Syntax error in subst macro. Bracket found, but third delimiter [%c] missing in [$%s].\n", separator, start ); - } - else { - Fatal( "Syntax error in subst macro. Third delimiter [%c] missing in [$%s].\n", separator, start ); + char *t1, *t2; + pat1 = DmSubStr( s, p ); + for(s=p=p+1; (*p != separator) && *p; p++ ); + /* Before the parsing fixes in iz36027 the :s macro modifier + * erroneously worked with patterns with missing pattern + * separator, i.e. $(XXX:s#pat#sub). This is an error because + * it prohibits the use of following macro modifiers. + * I.e. $(XXX:s#pat#sub:u) falsely replaces with "sub:u". + * ??? Remove this special case once OOo compiles without + * any of this warnings. */ + if( !*p ) { + if( *(p-1) == edelim ) { + p--; + Warning( "Syntax error in subst macro. Bracket found, but third delimiter [%c] missing in [$%s].\n", separator, start ); + } + else { + Fatal( "Syntax error in subst macro. Third delimiter [%c] missing in [$%s].\n", separator, start ); + } } - } - pat2 = DmSubStr( s, p ); - t1 = Expand(pat1); FREE(pat1); - t2 = Expand(pat2); FREE(pat2); - result = Apply_edit( result, t1, t2, TRUE, FALSE ); - FREE( t1 ); - FREE( t2 ); + pat2 = DmSubStr( s, p ); + t1 = Expand(pat1); FREE(pat1); + t2 = Expand(pat2); FREE(pat2); + result = Apply_edit( result, t1, t2, TRUE, FALSE ); + FREE( t1 ); + FREE( t2 ); } s = p; - } - /* find the end of the macro spec, or the start of a new - * modifier list for further processing of the result */ - - for( ; (*s != edelim) && (*s != ':') && *s; s++ ); - if( !*s ) - Fatal( "Syntax error in macro. [$%s].\n", start ); - if( *s == ':' ) s++; - break; - - case 'T': - case 't': - case '^': - case '+': - if( modifier_list ) { + } + /* find the end of the macro spec, or the start of a new + * modifier list for further processing of the result */ + + for( ; (*s != edelim) && (*s != ':') && *s; s++ ); + if( !*s ) + Fatal( "Syntax error in macro. [$%s].\n", start ); + if( *s == ':' ) s++; + break; + + case 'T': + case 't': + case '^': + case '+': + if( modifier_list ) { Warning( "Tokenize modifier must appear alone, ignored"); modifier_list = 0; - } - else { + } + else { separator = *s++; if( separator == '$' ) { - p = _scan_ballanced_parens(s,'\0'); - - if ( *p ) { - char *tmp; - pat1 = Expand(tmp = DmSubStr(s-1,p)); - FREE(tmp); - result = Tokenize(result, pat1, switch_char, TRUE); - FREE(pat1); - } - else { - Warning( "Incomplete macro expression [%s]", s ); - } - s = p; + p = _scan_ballanced_parens(s,'\0'); + + if ( *p ) { + char *tmp; + pat1 = Expand(tmp = DmSubStr(s-1,p)); + FREE(tmp); + result = Tokenize(result, pat1, switch_char, TRUE); + FREE(pat1); + } + else { + Warning( "Incomplete macro expression [%s]", s ); + } + s = p; } else if ( separator == '\"' ) { - /* we change the semantics to allow $(v:t")") */ - for (p = s; *p && *p != separator; p++) - if (*p == '\\') - if (p[1] == '\\' || p[1] == '"') - p++; - - if( *p == 0 ) - Fatal( "Unterminated separator string" ); - else { - pat1 = DmSubStr( s, p ); - result = Tokenize( result, pat1, switch_char, TRUE); - FREE( pat1 ); - } - s = p; + /* we change the semantics to allow $(v:t")") */ + for (p = s; *p && *p != separator; p++) + if (*p == '\\') + if (p[1] == '\\' || p[1] == '"') + p++; + + if( *p == 0 ) + Fatal( "Unterminated separator string" ); + else { + pat1 = DmSubStr( s, p ); + result = Tokenize( result, pat1, switch_char, TRUE); + FREE( pat1 ); + } + s = p; } else { Warning( - "Separator must be a quoted string or macro expression"); + "Separator must be a quoted string or macro expression"); } /* find the end of the macro spec, or the start of a new @@ -1035,26 +1035,26 @@ int doexpand; /* If TRUE enables macro expansion */ for( ; (*s != edelim) && (*s != ':'); s++ ); if( *s == ':' ) s++; - } - break; + } + break; - case ':': - if( modifier_list ) { + case ':': + if( modifier_list ) { result = Apply_modifiers( modifier_list, result ); modifier_list = 0; - } - break; + } + break; - default: - Warning( "Illegal modifier in macro, ignored" ); - break; - } - } + default: + Warning( "Illegal modifier in macro, ignored" ); + break; + } + } - if( modifier_list ) /* apply modifier */ - result = Apply_modifiers( modifier_list, result ); + if( modifier_list ) /* apply modifier */ + result = Apply_modifiers( modifier_list, result ); - s++; + s++; } *ps = s; @@ -1077,68 +1077,68 @@ char *s; char **ps; int *flag; { - char *t; - char *start; - char *res; - int lev = 1; - int done = 0; - - DB_ENTER( "_scan_brace" ); - - start = s; - while( !done ) - switch( *s++ ) { - case '{': - if( *s == '{' ) break; /* ignore {{ */ - lev++; - break; - - case '}': - if( *s == '}' ) break; /* ignore }} */ - if( lev ) - if( --lev == 0 ) done = TRUE; - break; - - case '$': - if( *s == '{' || *s == '}' ) { - if( (t = strchr(s,'}')) != NIL(char) ) - s = t; - s++; - } - break; + char *t; + char *start; + char *res; + int lev = 1; + int done = 0; + + DB_ENTER( "_scan_brace" ); + + start = s; + while( !done ) + switch( *s++ ) { + case '{': + if( *s == '{' ) break; /* ignore {{ */ + lev++; + break; + + case '}': + if( *s == '}' ) break; /* ignore }} */ + if( lev ) + if( --lev == 0 ) done = TRUE; + break; + + case '$': + if( *s == '{' || *s == '}' ) { + if( (t = strchr(s,'}')) != NIL(char) ) + s = t; + s++; + } + break; - case '\0': - if( lev ) { - done = TRUE; - s--; - /* error malformed macro expansion */ - } - break; + case '\0': + if( lev ) { + done = TRUE; + s--; + /* error malformed macro expansion */ } + break; + } - start = DmSubStr( start, (lev) ? s : s-1 ); + start = DmSubStr( start, (lev) ? s : s-1 ); - if( lev ) { - /* Braces were not ballanced so just return the string. - * Do not expand it. */ + if( lev ) { + /* Braces were not ballanced so just return the string. + * Do not expand it. */ - res = DmStrJoin( "{", start, -1, FALSE ); - *flag = 0; - } - else { - *flag = 1; - res = Expand( start ); + res = DmStrJoin( "{", start, -1, FALSE ); + *flag = 0; + } + else { + *flag = 1; + res = Expand( start ); - if( (t = DmStrSpn( res, " \t" )) != res ) { - size_t len = strlen(t)+1; - memmove( res, t, len ); - } - } + if( (t = DmStrSpn( res, " \t" )) != res ) { + size_t len = strlen(t)+1; + memmove( res, t, len ); + } + } - FREE( start ); /* this is ok! start is assigned a DmSubStr above */ - *ps = s; + FREE( start ); /* this is ok! start is assigned a DmSubStr above */ + *ps = s; - DB_RETURN( res ); + DB_RETURN( res ); } @@ -1155,31 +1155,31 @@ _cross_prod( x, y )/* char *x; char *y; { - static char *buf = NULL; - static int buf_siz = 0; - char *brkx; - char *brky; - char *cy; - char *cx; - char *res; - int i; - - if( *x && *y ) { - res = DmStrDup( "" ); cx = x; - while( *cx ) { - cy = y; - brkx = DmStrPbrk( cx, " \t\n" ); - if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx; - - while( *cy ) { + static char *buf = NULL; + static int buf_siz = 0; + char *brkx; + char *brky; + char *cy; + char *cx; + char *res; + int i; + + if( *x && *y ) { + res = DmStrDup( "" ); cx = x; + while( *cx ) { + cy = y; + brkx = DmStrPbrk( cx, " \t\n" ); + if( (brkx-cx == 2) && *cx == '\"' && *(cx+1) == '\"' ) cx = brkx; + + while( *cy ) { brky = DmStrPbrk( cy, " \t\n" ); if( (brky-cy == 2) && *cy == '\"' && *(cy+1) == '\"' ) cy = brky; i = brkx-cx + brky-cy + 2; if( i > buf_siz ) { /* grow buf to the correct size */ - if( buf != NIL(char) ) FREE( buf ); - if( (buf = MALLOC( i, char )) == NIL(char)) No_ram(); - buf_siz = i; + if( buf != NIL(char) ) FREE( buf ); + if( (buf = MALLOC( i, char )) == NIL(char)) No_ram(); + buf_siz = i; } strncpy( buf, cx, (i = brkx-cx) ); @@ -1189,16 +1189,16 @@ char *y; strcat( buf, " " ); res = DmStrJoin( res, buf, -1, TRUE ); cy = DmStrSpn( brky, " \t\n" ); - } - cx = DmStrSpn( brkx, " \t\n" ); } + cx = DmStrSpn( brkx, " \t\n" ); + } - FREE( x ); - res[ strlen(res)-1 ] = '\0'; - } - else - res = DmStrJoin( x, y, -1, TRUE ); + FREE( x ); + res[ strlen(res)-1 ] = '\0'; + } + else + res = DmStrJoin( x, y, -1, TRUE ); - FREE( y ); - return( res ); + FREE( y ); + return( res ); } diff --git a/dmake/function.c b/dmake/function.c index c0942db09213..cd86810849e5 100644 --- a/dmake/function.c +++ b/dmake/function.c @@ -465,45 +465,45 @@ static char * _exec_uniq( args ) char *args; { - char *res = NIL(char); - char *data = Expand(args); - char **tokens; - char **tokens_after; - char *p; - char *white = " \t\n"; - int j; - int i; - char *last = ""; - int k = 0; - - for(i=0,p=DmStrSpn(data,white);*p;p=DmStrSpn(DmStrPbrk(p,white),white),i++); - - if( i != 0 ) { - TALLOC(tokens, i, char *); - TALLOC(tokens_after, i, char *); - - for( i=0,p=DmStrSpn(data,white); *p; p=DmStrSpn(p,white),i++){ - tokens[i] = p; - p = DmStrPbrk(p,white); - if( *p ) *p++ = '\0'; - } - - qsort( tokens, i, sizeof(char *), _mystrcmp ); - - for( j=0; jce_attr & A_NOINFER ) {DB_VOID_RETURN;} - - DB_PRINT("inf", ("Inferring rule for [%s]", cp->CE_NAME)); - - match = NIL(ICELL); - nomatch = add_iset( NIL(ICELL), NIL(ICELL), NIL(CELL), NIL(DFALINK), - setdirroot, Prep+count_dots(cp->CE_NAME), 0, - DmStrDup(cp->CE_NAME), NIL(char), - cp->ce_time != (time_t)0L); - - /* Make sure we try whole heartedly to infer at least one suffix */ - if( nomatch->ic_dmax == 0 ) ++nomatch->ic_dmax; - - DB_EXECUTE( "inf", _dump_iset("nomatch",nomatch); ); - - /* If nomatch is non-empty there was no match with an existing - * prerrequisite, try to derive one. */ - while( nomatch != NIL(ICELL) ) { - ICELLPTR new_nomatch = NIL(ICELL); - ICELLPTR ic, pmatch, mmatch; - CELLPTR prereq; - - for( ic=nomatch; ic != NIL(ICELL); ic=ic->ic_next ) { - int ipush = FALSE; - - if( ic->ic_dir ) ipush = Push_dir(ic->ic_dir, ic->ic_name, FALSE); - match = union_iset(match, derive_prerequisites(ic, &new_nomatch)); - if( ipush ) Pop_dir(FALSE); - } - - DB_EXECUTE( "inf", _dump_iset("match",match); ); - DB_EXECUTE( "inf", _dump_iset("nomatch",new_nomatch); ); - - /* We have now deduced the two sets MATCH and NOMATCH. MATCH holds the - * set of edges that we encountered that matched. If this set is empty - * then we can apply transitive closure (if enabled) to the elements of - * NOMATCH to see if we can find some other method to make the target. - * - * If MATCH is non-empty, we have found a method for making the target. - * It is the shortest method for doing so (ie. uses fewest number of - * steps). If MATCH contains more than one element then we have a - * possible ambiguity. - */ - if( match == NIL(ICELL) ) { - nomatch = new_nomatch; - - /* Skip the rest and try one level deeper. */ - if( Transitive ) continue; - - goto all_done; - } - - /* Ok, we have a set of possible matches in MATCH, we should check the - * set for ambiguity. If more than one inference path exists of the - * same depth, then we may issue an ambiguous inference error message. - * - * The message is suppressed if MATCH contains two elements and one of - * them is the empty-prerequisite-rule. In this case we ignore the - * ambiguity and take the rule that infers the prerequisite. - * - * Also if there are any chains that rely on a non-existant prerequisite - * that may get made because it has a recipe then we prefer any that - * rely on existing final prerequisites over those that we have to make. - */ - - /* Split out those that have to be made from those that end in - * prerequisites that already exist. */ - pmatch = mmatch = NIL(ICELL); - for(; match; match = ic ) { - /* This loop checks all possible matches. */ - DB_PRINT("inf", ("Target [%s] : prerequisite [%s]", - match->ic_meta->CE_NAME, match->ic_name)); - - ic = match->ic_next; - match->ic_next = NIL(ICELL); - - if( match->ic_exists ) + ICELLPTR nomatch, match; + + DB_ENTER("Infer_recipe"); + + if( cp->ce_attr & A_NOINFER ) {DB_VOID_RETURN;} + + DB_PRINT("inf", ("Inferring rule for [%s]", cp->CE_NAME)); + + match = NIL(ICELL); + { + char *tmp; + nomatch = add_iset( NIL(ICELL), NIL(ICELL), NIL(CELL), NIL(DFALINK), + setdirroot, Prep+count_dots(cp->CE_NAME), 0, + tmp = DmStrDup(cp->CE_NAME), NIL(char), + cp->ce_time != (time_t)0L); + FREE(tmp); + } + + /* Make sure we try whole heartedly to infer at least one suffix */ + if( nomatch->ic_dmax == 0 ) ++nomatch->ic_dmax; + + DB_EXECUTE( "inf", _dump_iset("nomatch",nomatch); ); + + /* If nomatch is non-empty there was no match with an existing + * prerrequisite, try to derive one. */ + while( nomatch != NIL(ICELL) ) { + ICELLPTR new_nomatch = NIL(ICELL); + ICELLPTR ic, pmatch, mmatch; + CELLPTR prereq; + + for( ic=nomatch; ic != NIL(ICELL); ic=ic->ic_next ) { + int ipush = FALSE; + + if( ic->ic_dir ) ipush = Push_dir(ic->ic_dir, ic->ic_name, FALSE); + match = union_iset(match, derive_prerequisites(ic, &new_nomatch)); + if( ipush ) Pop_dir(FALSE); + } + + DB_EXECUTE( "inf", _dump_iset("match",match); ); + DB_EXECUTE( "inf", _dump_iset("nomatch",new_nomatch); ); + + /* We have now deduced the two sets MATCH and NOMATCH. MATCH holds the + * set of edges that we encountered that matched. If this set is empty + * then we can apply transitive closure (if enabled) to the elements of + * NOMATCH to see if we can find some other method to make the target. + * + * If MATCH is non-empty, we have found a method for making the target. + * It is the shortest method for doing so (ie. uses fewest number of + * steps). If MATCH contains more than one element then we have a + * possible ambiguity. + */ + if( match == NIL(ICELL) ) { + nomatch = new_nomatch; + + /* Skip the rest and try one level deeper. */ + if( Transitive ) continue; + + goto all_done; + } + + /* Ok, we have a set of possible matches in MATCH, we should check the + * set for ambiguity. If more than one inference path exists of the + * same depth, then we may issue an ambiguous inference error message. + * + * The message is suppressed if MATCH contains two elements and one of + * them is the empty-prerequisite-rule. In this case we ignore the + * ambiguity and take the rule that infers the prerequisite. + * + * Also if there are any chains that rely on a non-existant prerequisite + * that may get made because it has a recipe then we prefer any that + * rely on existing final prerequisites over those that we have to make. + */ + + /* Split out those that have to be made from those that end in + * prerequisites that already exist. */ + pmatch = mmatch = NIL(ICELL); + for(; match; match = ic ) { + /* This loop checks all possible matches. */ + DB_PRINT("inf", ("Target [%s] : prerequisite [%s]", + match->ic_meta->CE_NAME, match->ic_name)); + + ic = match->ic_next; + match->ic_next = NIL(ICELL); + + if( match->ic_exists ) pmatch = union_iset(pmatch, match); - else + else mmatch = union_iset(mmatch, match); - } + } - /* Prefer %-targets with existing prerequisites. */ - if( pmatch ) - match = pmatch; - else - match = mmatch; + /* Prefer %-targets with existing prerequisites. */ + if( pmatch ) + match = pmatch; + else + match = mmatch; - /* Make sure it is unique. It would be easy to check - * match->ic_meta->ce_prq for existence and prefer no prerequisites - * over prerequisites that are present, but we are currently not - * doing it. */ - if( match->ic_next != NIL(ICELL) ) { - int count = 1; + /* Make sure it is unique. It would be easy to check + * match->ic_meta->ce_prq for existence and prefer no prerequisites + * over prerequisites that are present, but we are currently not + * doing it. */ + if( match->ic_next != NIL(ICELL) ) { + int count = 1; - Warning( "Ambiguous inference chains for target '%s'", cp->CE_NAME ); - for( ic=match; ic; ic=ic->ic_next ) + Warning( "Ambiguous inference chains for target '%s'", cp->CE_NAME ); + for( ic=match; ic; ic=ic->ic_next ) (void) dump_inf_chain(ic, TRUE, count++); - Warning( "First matching rule is chosen."); - } - - /* MATCH now points at the derived prerequisite chain(s). We must now - * take cp, and construct the correct graph so that the make may - * proceed. */ - - /* The folowing shows only the first element, i.e. the last matching - * recipe that was found. */ - if( Verbose & V_INFER ) { - char *tmp = dump_inf_chain(match, TRUE, FALSE); - printf("%s: Inferring prerequistes and recipes using:\n%s: ... %s\n", - Pname, Pname, tmp ); - FREE(tmp); } + Warning( "First matching rule is chosen."); + } + + /* MATCH now points at the derived prerequisite chain(s). We must now + * take cp, and construct the correct graph so that the make may + * proceed. */ + + /* The folowing shows only the first element, i.e. the last matching + * recipe that was found. */ + if( Verbose & V_INFER ) { + char *tmp = dump_inf_chain(match, TRUE, FALSE); + printf("%s: Inferring prerequistes and recipes using:\n%s: ... %s\n", + Pname, Pname, tmp ); + FREE(tmp); + } - pmatch = NIL(ICELL); - prereq = NIL(CELL); + pmatch = NIL(ICELL); + prereq = NIL(CELL); - /* This loop treats the inferred targets last to first. */ - while( match ) { - CELLPTR infcell=NIL(CELL); + /* This loop treats the inferred targets last to first. */ + while( match ) { + CELLPTR infcell=NIL(CELL); - /* Compute the inferred prerequisite first. */ - if( match->ic_name ) { + /* Compute the inferred prerequisite first. */ + if( match->ic_name ) { if( match->ic_meta ) - infcell = Def_cell( match->ic_name ); + infcell = Def_cell( match->ic_name ); else - infcell = cp; + infcell = cp; infcell->ce_flag |= F_TARGET; if( infcell != cp ) { - infcell->ce_flag |= F_INFER|F_REMOVE; - DB_PRINT("remove", ("Mark for deletion [%s]", - infcell->CE_NAME)); + infcell->ce_flag |= F_INFER|F_REMOVE; + DB_PRINT("remove", ("Mark for deletion [%s]", + infcell->CE_NAME)); } if( !match->ic_flag ) - infcell->ce_attr |= A_NOINFER; - } + infcell->ce_attr |= A_NOINFER; + } - /* Add global prerequisites from previous rule if there are any and - * the recipe. */ - if( pmatch ) { + /* Add global prerequisites from previous rule if there are any and + * the recipe. */ + if( pmatch ) { CELLPTR imeta = pmatch->ic_meta; LINKPTR lp; DB_PRINT("inf", ("%%-target [%s] - infered target [%s]\n", - imeta->CE_NAME, infcell->CE_NAME)); + imeta->CE_NAME, infcell->CE_NAME)); infcell->ce_per = pmatch->ic_dfa->dl_per; infcell->ce_attr |= (imeta->ce_attr & A_TRANSFER); @@ -226,31 +231,31 @@ CELLPTR setdirroot; * the this target it might have been created and stated * therefore these values need to be reset. */ if( infcell->ce_attr & A_PHONY ){ - infcell->ce_time = 0L; - infcell->ce_flag &= ~F_STAT; + infcell->ce_time = 0L; + infcell->ce_flag &= ~F_STAT; } if( !(infcell->ce_flag & F_RULES) ) { - infcell->ce_flag |= (imeta->ce_flag&(F_SINGLE|F_GROUP))|F_RULES; - infcell->ce_recipe = imeta->ce_recipe; + infcell->ce_flag |= (imeta->ce_flag&(F_SINGLE|F_GROUP))|F_RULES; + infcell->ce_recipe = imeta->ce_recipe; } /* Add any conditional macro definitions that may be associated * with the inferred cell. */ if (imeta->ce_cond != NIL(STRING)) { - STRINGPTR sp,last; - - last = infcell->ce_cond; - for(sp=imeta->ce_cond; sp; sp=sp->st_next) { - STRINGPTR new; - TALLOC(new, 1, STRING); - new->st_string = DmStrDup(sp->st_string); - if(last) - last->st_next = new; - else - infcell->ce_cond = new; - last = new; - } + STRINGPTR sp,last; + + last = infcell->ce_cond; + for(sp=imeta->ce_cond; sp; sp=sp->st_next) { + STRINGPTR new; + TALLOC(new, 1, STRING); + new->st_string = DmStrDup(sp->st_string); + if(last) + last->st_next = new; + else + infcell->ce_cond = new; + last = new; + } } pmatch->ic_dfa->dl_per = NIL(char); @@ -258,63 +263,63 @@ CELLPTR setdirroot; /* If infcell already had a .SETDIR directory set then modify it * based on whether it was the original cell or some intermediary. */ if( imeta->ce_dir ) { - if( infcell->ce_dir && infcell == cp ) { - /* cp->ce_dir was set and we have pushed the directory prior - * to calling this routine. - * We build a new path by appending imeta->ce_dir to the - * current directory of the original cell. - * We should therefore pop it and push the new concatenated - * directory required by the inference. - * This leaks memory as cp->ce_dir is not freed before - * setting the new the new infcell->ce_dir value but as - * the pointer could be a `A_POOL` member we accept this. */ - infcell->ce_dir = DmStrDup(Build_path(infcell->ce_dir, - imeta->ce_dir)); - } - else { - /* Inherit a copy of the .SETDIR value. Use a copy because - * the original could have been freed in the meantime - * in Make() by the FREE() before _pool_lookup(). This can - * also leak if infcell->ce_dir was set before. */ - infcell->ce_dir = DmStrDup(imeta->ce_dir); - } + if( infcell->ce_dir && infcell == cp ) { + /* cp->ce_dir was set and we have pushed the directory prior + * to calling this routine. + * We build a new path by appending imeta->ce_dir to the + * current directory of the original cell. + * We should therefore pop it and push the new concatenated + * directory required by the inference. + * This leaks memory as cp->ce_dir is not freed before + * setting the new the new infcell->ce_dir value but as + * the pointer could be a `A_POOL` member we accept this. */ + infcell->ce_dir = DmStrDup(Build_path(infcell->ce_dir, + imeta->ce_dir)); + } + else { + /* Inherit a copy of the .SETDIR value. Use a copy because + * the original could have been freed in the meantime + * in Make() by the FREE() before _pool_lookup(). This can + * also leak if infcell->ce_dir was set before. */ + infcell->ce_dir = DmStrDup(imeta->ce_dir); + } } for( lp=imeta->ce_indprq; lp != NIL(LINK); lp=lp->cl_next ) { - char *name = lp->cl_prq->CE_NAME; - CELLPTR tcp; - - name = buildname( cp->CE_NAME, name, infcell->ce_per ); - tcp = Def_cell( name ); - tcp->ce_flag |= F_REMOVE; - Add_prerequisite( infcell, tcp, FALSE, FALSE ); - - if( Verbose & V_INFER ) - printf( "%s: Inferred indirect prerequisite [%s]\n", - Pname, name ); - FREE(name); + char *name = lp->cl_prq->CE_NAME; + CELLPTR tcp; + + name = buildname( cp->CE_NAME, name, infcell->ce_per ); + tcp = Def_cell( name ); + tcp->ce_flag |= F_REMOVE; + Add_prerequisite( infcell, tcp, FALSE, FALSE ); + + if( Verbose & V_INFER ) + printf( "%s: Inferred indirect prerequisite [%s]\n", + Pname, name ); + FREE(name); } - } + } - /* Add the previous cell as the prerequisite */ - if( prereq ) + /* Add the previous cell as the prerequisite */ + if( prereq ) (Add_prerequisite(infcell,prereq,FALSE,FALSE))->cl_flag |=F_TARGET; - pmatch = match; /* Previous member in inference chain ... */ - prereq = infcell; /* is a prerequisite to the next match. */ - /* ip->ic_parent is the next target in the inference chain to be - * build. If it is empty we are done. */ - match = match->ic_parent; - } + pmatch = match; /* Previous member in inference chain ... */ + prereq = infcell; /* is a prerequisite to the next match. */ + /* ip->ic_parent is the next target in the inference chain to be + * build. If it is empty we are done. */ + match = match->ic_parent; + } - DB_PRINT("inf", ("Terminated due to a match")); - break; - } + DB_PRINT("inf", ("Terminated due to a match")); + break; + } -all_done: - free_icells(); + all_done: + free_icells(); - DB_VOID_RETURN; + DB_VOID_RETURN; } diff --git a/dmake/parse.c b/dmake/parse.c index 2344192b8541..550f14223a91 100644 --- a/dmake/parse.c +++ b/dmake/parse.c @@ -35,142 +35,142 @@ Parse( fil )/* ============== Parse the makefile input */ FILE *fil; { - int rule = FALSE; /* have seen a recipe line */ - char *p; /* termporary pointer into Buffer */ - char *pTmpBuf; + int rule = FALSE; /* have seen a recipe line */ + char *p; /* termporary pointer into Buffer */ + char *pTmpBuf; - DB_ENTER( "Parse" ); + DB_ENTER( "Parse" ); - State = NORMAL_SCAN; - Group = FALSE; /* true if scanning a group rcpe */ - while( TRUE ) { - if( Get_line( Buffer, fil ) ) { - if( Group ) Fatal( "Incomplete rule recipe group detected" ); + State = NORMAL_SCAN; + Group = FALSE; /* true if scanning a group rcpe */ + while( TRUE ) { + if( Get_line( Buffer, fil ) ) { + if( Group ) Fatal( "Incomplete rule recipe group detected" ); - /* If we are still in RULE_SCAN mode there might be unbound recipes. */ - if( State == RULE_SCAN ) + /* If we are still in RULE_SCAN mode there might be unbound recipes. */ + if( State == RULE_SCAN ) Bind_rules_to_targets( F_DEFAULT ); - if( fil != NIL( FILE ) ) /* end of parsable input */ + if( fil != NIL( FILE ) ) /* end of parsable input */ Closefile(); - DB_VOID_RETURN; - } - else { + DB_VOID_RETURN; + } + else { #ifdef _MPW - if ( Buffer[0] == 10 ) - pTmpBuf = Buffer+1; - else + if ( Buffer[0] == 10 ) + pTmpBuf = Buffer+1; + else #endif - pTmpBuf = Buffer; + pTmpBuf = Buffer; #ifdef _MPW - p = pTmpBuf; - while ( *p ) - { - if ( *p == 10 ) - *p = '\t'; - p++; - } + p = pTmpBuf; + while ( *p ) + { + if ( *p == 10 ) + *p = '\t'; + p++; + } #endif - switch( State ) { - case RULE_SCAN: + switch( State ) { + case RULE_SCAN: - /* Check for the `[' that starts off a group recipe definition. - * It must appear as the first non-white space - * character in the line. */ + /* Check for the `[' that starts off a group recipe definition. + * It must appear as the first non-white space + * character in the line. */ - p = DmStrSpn( Buffer, " \t\r\n" ); - if( Set_group_attributes( p ) ) { + p = DmStrSpn( Buffer, " \t\r\n" ); + if( Set_group_attributes( p ) ) { if( Group ) - Fatal( "New group recipe begin found within group recipe." ); + Fatal( "New group recipe begin found within group recipe." ); else if( rule ) - Fatal( "Cannot mix single and group recipe lines." ); + Fatal( "Cannot mix single and group recipe lines." ); + else + Group = TRUE; + + rule = TRUE; + + break; /* ignore the group start */ + } + + if( Group ) { + if( *p != ']' ) { + Add_recipe_to_list( pTmpBuf, TRUE, TRUE ); + rule = TRUE; + } else - Group = TRUE; - - rule = TRUE; - - break; /* ignore the group start */ - } - - if( Group ) { - if( *p != ']' ) { - Add_recipe_to_list( pTmpBuf, TRUE, TRUE ); - rule = TRUE; - } - else - State = NORMAL_SCAN; - } - else { - if( *pTmpBuf == '\t' - || (Notabs && *pTmpBuf == ' ') ) { - Add_recipe_to_list( pTmpBuf, FALSE, FALSE ); - rule = TRUE; - } - else if( *p == ']' ) - Fatal( "Found unmatched ']'" ); - else if( *pTmpBuf ) /* Something that was no recipe. */ - State = NORMAL_SCAN; + State = NORMAL_SCAN; + } + else { + if( *pTmpBuf == '\t' + || (Notabs && *pTmpBuf == ' ') ) { + Add_recipe_to_list( pTmpBuf, FALSE, FALSE ); + rule = TRUE; + } + else if( *p == ']' ) + Fatal( "Found unmatched ']'" ); + else if( *pTmpBuf ) /* Something that was no recipe. */ + State = NORMAL_SCAN; /* The only thing that was not handled was an empty line. */ - } + } - if( State == RULE_SCAN ) break; /* ie. keep going */ + if( State == RULE_SCAN ) break; /* ie. keep going */ - Bind_rules_to_targets( (Group) ? F_GROUP: F_DEFAULT ); + Bind_rules_to_targets( (Group) ? F_GROUP: F_DEFAULT ); - rule = FALSE; - if( Group ) { - Group = FALSE; - break; - } - /*FALLTRHOUGH*/ + rule = FALSE; + if( Group ) { + Group = FALSE; + break; + } + /*FALLTRHOUGH*/ - /* In this case we broke out of the rule scan because we do not - * have a recipe line that begins with a , so lets - * try to scan the thing as a macro or rule definition. */ + /* In this case we broke out of the rule scan because we do not + * have a recipe line that begins with a , so lets + * try to scan the thing as a macro or rule definition. */ - case NORMAL_SCAN: - if( !*pTmpBuf ) continue; /* we have null input line */ + case NORMAL_SCAN: + if( !*pTmpBuf ) continue; /* we have null input line */ - /* STUPID AUGMAKE uses "include" at the start of a line as - * a signal to include a new file, so let's look for it. - * if we see it replace it by .INCLUDE: and stick this back - * into the buffer. */ - if( !strncmp( "include", pTmpBuf, 7 ) && - (pTmpBuf[7] == ' ' || pTmpBuf[7] == '\t') ) - { - char *tmp; + /* STUPID AUGMAKE uses "include" at the start of a line as + * a signal to include a new file, so let's look for it. + * if we see it replace it by .INCLUDE: and stick this back + * into the buffer. */ + if( !strncmp( "include", pTmpBuf, 7 ) && + (pTmpBuf[7] == ' ' || pTmpBuf[7] == '\t') ) + { + char *tmp; - tmp = DmStrJoin( ".INCLUDE:", pTmpBuf+7, -1, FALSE ); - strcpy( pTmpBuf, tmp ); - FREE( tmp ); - } + tmp = DmStrJoin( ".INCLUDE:", pTmpBuf+7, -1, FALSE ); + strcpy( pTmpBuf, tmp ); + FREE( tmp ); + } - /* look for a macro definition, they all contain an = sign - * if we fail to recognize it as a legal macro op then try to - * parse the same line as a rule definition, it's one or the - * other */ + /* look for a macro definition, they all contain an = sign + * if we fail to recognize it as a legal macro op then try to + * parse the same line as a rule definition, it's one or the + * other */ - if( Parse_macro(pTmpBuf, M_DEFAULT) ) break;/* it's a macro def*/ - if( Parse_rule_def( &State ) ) break;/* it's a rule def */ + if( Parse_macro(pTmpBuf, M_DEFAULT) ) break;/* it's a macro def*/ + if( Parse_rule_def( &State ) ) break;/* it's a rule def */ - /* if it is an empty or blank line then ignore it */ - if( !*Buffer || *DmStrSpn( Buffer, " \t\r\n" ) == '\0' ) break; + /* if it is an empty or blank line then ignore it */ + if( !*Buffer || *DmStrSpn( Buffer, " \t\r\n" ) == '\0' ) break; - /* otherwise assume it was a line of unrecognized input, or a - * recipe line out of place so print a message */ + /* otherwise assume it was a line of unrecognized input, or a + * recipe line out of place so print a message */ - Fatal( "Expecting macro or rule defn, found neither" ); - break; + Fatal( "Expecting macro or rule defn, found neither" ); + break; - default: - Fatal( "Internal -- UNKNOWN Parser state %d", State ); - } + default: + Fatal( "Internal -- UNKNOWN Parser state %d", State ); } - } + } + } } diff --git a/dmake/rulparse.c b/dmake/rulparse.c index af7915fb129b..f47f166ef7ae 100644 --- a/dmake/rulparse.c +++ b/dmake/rulparse.c @@ -75,72 +75,72 @@ Parse_rule_def( state )/* */ int *state; { - TKSTR input; /* input string struct for token search */ - CELLPTR targets; /* list of targets if any */ - CELLPTR prereq; /* list of prereq if any */ - CELLPTR prereqtail; /* tail of prerequisite list */ - CELLPTR cp; /* temporary cell pointer for list making */ - char *result; /* temporary storage for result */ - char *tok; /* temporary pointer for tokens */ - char *set_dir; /* value of setdir attribute */ - char *brk; /* break char list for Get_token */ - char *firstrcp; /* first recipe line, from ; in rule line */ - t_attr attr; /* sum of attribute flags for current tgts*/ - t_attr at; /* temp place to keep an attribute code */ - int op; /* rule operator */ - int special; /* indicate special targets in rule */ - int augmeta; /* indicate . like target */ - int percent; /* indicate percent rule target */ - int percent_prq; /* indicate mixed %-rule prereq possible */ - - DB_ENTER( "Parse_rule_def" ); - - op = 0; - attr = 0; - special = 0; - augmeta = 0; - percent = 0; - set_dir = NIL( char ); - targets = NIL(CELL); - prereq = NIL(CELL); - prereqtail = NIL(CELL); - percent_prq = 0; - - /* Check to see if the line is of the form: - * targets : prerequisites; first recipe line - * If so remember the first_recipe part of the line. */ - - firstrcp = strchr( Buffer, ';' ); - if( firstrcp != NIL( char ) ) { - *firstrcp++ = 0; - firstrcp = DmStrSpn( firstrcp, " \t" ); - } - - result = Expand( Buffer ); - /* Remove CONTINUATION_CHAR, keep the */ - for( brk=strchr(result,CONTINUATION_CHAR); brk != NIL(char); brk=strchr(brk,CONTINUATION_CHAR) ) - if( brk[1] == '\n' ) - *brk = ' '; - else - brk++; - - DB_PRINT( "par", ("Scanning: [%s]", result) ); - - SET_TOKEN( &input, result ); - brk = ":-^!|"; - Def_targets = TRUE; + TKSTR input; /* input string struct for token search */ + CELLPTR targets; /* list of targets if any */ + CELLPTR prereq; /* list of prereq if any */ + CELLPTR prereqtail; /* tail of prerequisite list */ + CELLPTR cp; /* temporary cell pointer for list making */ + char *result; /* temporary storage for result */ + char *tok; /* temporary pointer for tokens */ + char *set_dir; /* value of setdir attribute */ + char *brk; /* break char list for Get_token */ + char *firstrcp; /* first recipe line, from ; in rule line */ + t_attr attr; /* sum of attribute flags for current tgts*/ + t_attr at; /* temp place to keep an attribute code */ + int op; /* rule operator */ + int special; /* indicate special targets in rule */ + int augmeta; /* indicate . like target */ + int percent; /* indicate percent rule target */ + int percent_prq; /* indicate mixed %-rule prereq possible */ + + DB_ENTER( "Parse_rule_def" ); + + op = 0; + attr = 0; + special = 0; + augmeta = 0; + percent = 0; + set_dir = NIL( char ); + targets = NIL(CELL); + prereq = NIL(CELL); + prereqtail = NIL(CELL); + percent_prq = 0; + + /* Check to see if the line is of the form: + * targets : prerequisites; first recipe line + * If so remember the first_recipe part of the line. */ + + firstrcp = strchr( Buffer, ';' ); + if( firstrcp != NIL( char ) ) { + *firstrcp++ = 0; + firstrcp = DmStrSpn( firstrcp, " \t" ); + } + + result = Expand( Buffer ); + /* Remove CONTINUATION_CHAR, keep the */ + for( brk=strchr(result,CONTINUATION_CHAR); brk != NIL(char); brk=strchr(brk,CONTINUATION_CHAR) ) + if( brk[1] == '\n' ) + *brk = ' '; + else + brk++; + + DB_PRINT( "par", ("Scanning: [%s]", result) ); + + SET_TOKEN( &input, result ); + brk = ":-^!|"; + Def_targets = TRUE; + + /* Scan the input rule line collecting targets, the operator, and any + * prerequisites. Stop when we run out of targets and prerequisites. */ + + while( *(tok = Get_token( &input, brk, TRUE )) != '\0' ) + if( !op ) { + /* we are scanning targets and attributes + * check to see if token is an operator. */ + + op = Rule_op( tok ); - /* Scan the input rule line collecting targets, the operator, and any - * prerequisites. Stop when we run out of targets and prerequisites. */ - - while( *(tok = Get_token( &input, brk, TRUE )) != '\0' ) if( !op ) { - /* we are scanning targets and attributes - * check to see if token is an operator. */ - - op = Rule_op( tok ); - - if( !op ) { /* Define a new cell, or get pointer to pre-existing cell. */ /* Do we need cells for attributes? If not move the definition * to the target part. */ @@ -151,209 +151,209 @@ int *state; DB_PRINT( "par", ("tg_cell [%s]", tok) ); if( (at = _is_attribute(tok)) != 0 ) { - /* Ignore .SILENT when -vr is active. */ - if( (Verbose & V_FORCEECHO) && (at == A_SILENT) ) - at = 0; + /* Ignore .SILENT when -vr is active. */ + if( (Verbose & V_FORCEECHO) && (at == A_SILENT) ) + at = 0; - /* Logically OR the attributes specified into one main - * ATTRIBUTE mask. */ + /* Logically OR the attributes specified into one main + * ATTRIBUTE mask. */ - if( at == A_SETDIR ) { - if( set_dir != NIL( char ) ) - Warning( "Multiple .SETDIR attribute ignored" ); - else - set_dir = DmStrDup( tok ); - } + if( at == A_SETDIR ) { + if( set_dir != NIL( char ) ) + Warning( "Multiple .SETDIR attribute ignored" ); + else + set_dir = DmStrDup( tok ); + } - attr |= at; + attr |= at; } else { - /* Not an attribute, this must be a target. */ - int tmp; - - tmp = _is_special( tok ); - - if( _is_percent( tok ) ) { - /* First %-target checks if there were non-%-targets before. */ - if( !percent && targets != NIL(CELL) ) - Fatal( "A %%-target must not be mixed with non-%%-targets, offending target [%s]", tok ); - - percent++; - cp->ce_flag |= F_PERCENT; - } else { - if( percent ) - Fatal( "A non-%%-target must not be mixed with %%-targets, offending target [%s]", tok ); - } - - if( _is_magic( tok ) ) { - /* Check that AUGMAKE targets are not mixed with other - * targets. The return value of _is_magic() is discarded and - * calculated again in _do_targets() if this rule definition - * really is a . like target. - * If we would allow only one target per line we could easily - * store the result for later, but for multiple . - * targets this creates too much overhead. - * These targets should be rare (obsolete?) anyway. */ - if( !augmeta && targets != NIL(CELL) ) - Fatal( "An AUGMAKE meta target must not be mixed with non AUGMAKE meta targets, offending target [%s]", tok ); - - augmeta++; - cp->ce_flag |= F_MAGIC; /* do_magic will also add F_PERCENT later. */ - } else { - if( augmeta ) - Fatal( "A non AUGMAKE meta target must not be mixed with AUGMAKE meta targets, offending target [%s]", tok ); - } - - if( special ) - Fatal( "Special target must appear alone, found [%s]", tok ); - else if( !(cp->ce_flag & F_MARK) ) { - /* Targets are kept in this list in lexically sorted order. - * This allows for easy equality comparison of target - * sets.*/ - CELLPTR prev,cur; - for(prev=NIL(CELL),cur=targets;cur;prev=cur,cur=cur->ce_link) - if(strcmp(cur->CE_NAME,cp->CE_NAME) > 0) - break; - - cp->ce_link = cur; - - if (!prev) - targets = cp; + /* Not an attribute, this must be a target. */ + int tmp; + + tmp = _is_special( tok ); + + if( _is_percent( tok ) ) { + /* First %-target checks if there were non-%-targets before. */ + if( !percent && targets != NIL(CELL) ) + Fatal( "A %%-target must not be mixed with non-%%-targets, offending target [%s]", tok ); + + percent++; + cp->ce_flag |= F_PERCENT; + } else { + if( percent ) + Fatal( "A non-%%-target must not be mixed with %%-targets, offending target [%s]", tok ); + } + + if( _is_magic( tok ) ) { + /* Check that AUGMAKE targets are not mixed with other + * targets. The return value of _is_magic() is discarded and + * calculated again in _do_targets() if this rule definition + * really is a . like target. + * If we would allow only one target per line we could easily + * store the result for later, but for multiple . + * targets this creates too much overhead. + * These targets should be rare (obsolete?) anyway. */ + if( !augmeta && targets != NIL(CELL) ) + Fatal( "An AUGMAKE meta target must not be mixed with non AUGMAKE meta targets, offending target [%s]", tok ); + + augmeta++; + cp->ce_flag |= F_MAGIC; /* do_magic will also add F_PERCENT later. */ + } else { + if( augmeta ) + Fatal( "A non AUGMAKE meta target must not be mixed with AUGMAKE meta targets, offending target [%s]", tok ); + } + + if( special ) + Fatal( "Special target must appear alone, found [%s]", tok ); + else if( !(cp->ce_flag & F_MARK) ) { + /* Targets are kept in this list in lexically sorted order. + * This allows for easy equality comparison of target + * sets.*/ + CELLPTR prev,cur; + for(prev=NIL(CELL),cur=targets;cur;prev=cur,cur=cur->ce_link) + if(strcmp(cur->CE_NAME,cp->CE_NAME) > 0) + break; + + cp->ce_link = cur; + + if (!prev) + targets = cp; + else + prev->ce_link = cp; + + cp->ce_flag |= F_MARK | F_EXPLICIT; + special = tmp; + } else - prev->ce_link = cp; - - cp->ce_flag |= F_MARK | F_EXPLICIT; - special = tmp; - } - else - Warning( "Duplicate target [%s]", cp->CE_NAME ); + Warning( "Duplicate target [%s]", cp->CE_NAME ); } - } - else { + } + else { /* found an operator so empty out break list and clear mark * bits on target list, setting them all to F_VISITED*/ brk = ""; for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) { - cp->ce_flag ^= F_MARK; - cp->ce_flag |= F_VISITED; + cp->ce_flag ^= F_MARK; + cp->ce_flag |= F_VISITED; } Def_targets = FALSE; - } } - else { - /* Scanning prerequisites so build the prerequisite list. We use - * F_MARK flag to make certain we have only a single copy of the - * prerequisite in the list */ + } + else { + /* Scanning prerequisites so build the prerequisite list. We use + * F_MARK flag to make certain we have only a single copy of the + * prerequisite in the list */ - cp = Def_cell( tok ); + cp = Def_cell( tok ); - /* %-prerequisits require eiter a %-target or this might be a rule of - * the "ATTRIBUTE_LIST : targets" form. */ - if( _is_percent( tok ) ) { + /* %-prerequisits require eiter a %-target or this might be a rule of + * the "ATTRIBUTE_LIST : targets" form. */ + if( _is_percent( tok ) ) { if( percent || ((targets == NIL(CELL)) && attr) ) - percent_prq = 1; + percent_prq = 1; else - Fatal( "Syntax error in %% rule, missing %% target"); - } + Fatal( "Syntax error in %% rule, missing %% target"); + } - if( cp->ce_flag & F_VISITED ) { + if( cp->ce_flag & F_VISITED ) { if( cp->ce_attr & A_COMPOSITE ) - continue; + continue; else - Fatal( "Detected circular dependency in graph at [%s]", - cp->CE_NAME ); - } - else if( !(cp->ce_flag & F_MARK) ) { + Fatal( "Detected circular dependency in graph at [%s]", + cp->CE_NAME ); + } + else if( !(cp->ce_flag & F_MARK) ) { DB_PRINT( "par", ("pq_cell [%s]", tok) ); cp->ce_flag |= F_MARK; if( prereqtail == NIL(CELL) ) /* keep prereq's in order */ - prereq = cp; + prereq = cp; else - prereqtail->ce_link = cp; + prereqtail->ce_link = cp; prereqtail = cp; cp->ce_link = NIL(CELL); - } - else if( !(cp->ce_attr & A_LIBRARY) && (Verbose & V_WARNALL)) - Warning("Duplicate entry [%s] in prerequisite list",cp->CE_NAME); } - - /* Check to see if we have a percent rule that has only global - * prerequisites, i.e. they are of the form: "%.a : foo". - * If so then set the flag so that later on, we don't issue - * an error if such targets supply an empty set of rules. */ - - if( percent && !percent_prq && (prereq != NIL(CELL)) ) - _sv_globprq_only = 1; - - /* It's ok to have targets with attributes, and no prerequisites, but it's - * not ok to have no targets and no attributes, or no operator */ - - if( !op ) { - CLEAR_TOKEN( &input ); - DB_PRINT( "par", ("Not a rule [%s]", Buffer) ); - DB_RETURN( 0 ); - } - - /* More than one percent target didn't work with prior versions. */ - if( (percent > 1) && !(op & R_OP_OR) ) - Warning( "Prior to dmake 4.5 only one\n" - "%%-target per target-definition worked reliably. Check your makefiles.\n" ); - - if( !attr && targets == NIL(CELL) ) { - Fatal( "Missing targets or attributes in rule" ); - if( set_dir != NIL( char )) FREE( set_dir ); - DB_RETURN( 0 ); - } - - /* We have established we have a legal rules line, so we must process it. - * In doing so we must handle any special targets. Special targets must - * appear alone possibly accompanied by attributes. - * NOTE: special != 0 ==> targets != NIL(CELL) */ - - if( prereqtail != NIL(CELL) ) prereqtail->ce_link = NIL(CELL); - - /* Clear out MARK bits used in duplicate checking. I originally wanted - * to do this as the lists get processed but that got too error prone - * so I bit the bullit and added these two loops. */ - - for( cp=prereq; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_MARK; - for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_VISITED; - - /* Check to see if the previous recipe was bound, if not the call - * Bind_rules_to_targets() to bind the recipe (_sv_rules) to the - * target(s) (_sv_targets). */ - /* was: if( _sv_rules != NIL(STRING) ) Bind_rules_to_targets( F_DEFAULT );*/ - /* Only Add_recipe_to_list() sets _sv_rules and Bind_rules_to_targets() - * clears the (static) variables again. Bind_rules_to_targets() is - * (should be) called after State is leaving RULE_SCAN in Parse(). - * Abort if there are unbound recipes. FIXME: Remove this paragraph - * if this never occurs. */ - if( _sv_rules != NIL(STRING) ) - Fatal( "Internal Error: _sv_rules not empty." ); - - /* Add the first recipe line to the list */ - if( firstrcp != NIL( char ) ) - Add_recipe_to_list( firstrcp, TRUE, FALSE ); - - /* Save these prior to calling _do_targets, since _build_graph needs the - * _sv_setdir value for matching edges. */ - _sv_op = op; - _sv_setdir = set_dir; - - if( special ) - /* _do_special() can alter *state */ - _do_special( special, op, attr, set_dir, targets, prereq, state ); - else - *state = _do_targets( op, attr, set_dir, targets, prereq ); - - if( (*state != RULE_SCAN) && (_sv_rules != NIL(STRING)) ) - Fatal( "Unexpected recipe found." ); - - DB_RETURN( 1 ); + else if( !(cp->ce_attr & A_LIBRARY) && (Verbose & V_WARNALL)) + Warning("Duplicate entry [%s] in prerequisite list",cp->CE_NAME); + } + + /* Check to see if we have a percent rule that has only global + * prerequisites, i.e. they are of the form: "%.a : foo". + * If so then set the flag so that later on, we don't issue + * an error if such targets supply an empty set of rules. */ + + if( percent && !percent_prq && (prereq != NIL(CELL)) ) + _sv_globprq_only = 1; + + /* It's ok to have targets with attributes, and no prerequisites, but it's + * not ok to have no targets and no attributes, or no operator */ + + CLEAR_TOKEN( &input ); FREE(result); result = NIL(char); + if( !op ) { + DB_PRINT( "par", ("Not a rule [%s]", Buffer) ); + DB_RETURN( 0 ); + } + + /* More than one percent target didn't work with prior versions. */ + if( (percent > 1) && !(op & R_OP_OR) ) + Warning( "Prior to dmake 4.5 only one\n" + "%%-target per target-definition worked reliably. Check your makefiles.\n" ); + + if( !attr && targets == NIL(CELL) ) { + Fatal( "Missing targets or attributes in rule" ); + if( set_dir != NIL( char )) FREE( set_dir ); + DB_RETURN( 0 ); + } + + /* We have established we have a legal rules line, so we must process it. + * In doing so we must handle any special targets. Special targets must + * appear alone possibly accompanied by attributes. + * NOTE: special != 0 ==> targets != NIL(CELL) */ + + if( prereqtail != NIL(CELL) ) prereqtail->ce_link = NIL(CELL); + + /* Clear out MARK bits used in duplicate checking. I originally wanted + * to do this as the lists get processed but that got too error prone + * so I bit the bullit and added these two loops. */ + + for( cp=prereq; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_MARK; + for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_VISITED; + + /* Check to see if the previous recipe was bound, if not the call + * Bind_rules_to_targets() to bind the recipe (_sv_rules) to the + * target(s) (_sv_targets). */ + /* was: if( _sv_rules != NIL(STRING) ) Bind_rules_to_targets( F_DEFAULT );*/ + /* Only Add_recipe_to_list() sets _sv_rules and Bind_rules_to_targets() + * clears the (static) variables again. Bind_rules_to_targets() is + * (should be) called after State is leaving RULE_SCAN in Parse(). + * Abort if there are unbound recipes. FIXME: Remove this paragraph + * if this never occurs. */ + if( _sv_rules != NIL(STRING) ) + Fatal( "Internal Error: _sv_rules not empty." ); + + /* Add the first recipe line to the list */ + if( firstrcp != NIL( char ) ) + Add_recipe_to_list( firstrcp, TRUE, FALSE ); + + /* Save these prior to calling _do_targets, since _build_graph needs the + * _sv_setdir value for matching edges. */ + _sv_op = op; + _sv_setdir = set_dir; + + if( special ) + /* _do_special() can alter *state */ + _do_special( special, op, attr, set_dir, targets, prereq, state ); + else + *state = _do_targets( op, attr, set_dir, targets, prereq ); + + if( (*state != RULE_SCAN) && (_sv_rules != NIL(STRING)) ) + Fatal( "Unexpected recipe found." ); + + DB_RETURN( 1 ); } @@ -576,240 +576,239 @@ CELLPTR target; CELLPTR prereq; int *state; { - HASHPTR hp; /* pointer to macro def cell */ - CELLPTR cp; /* temporary pointer into cells list */ - CELLPTR dp; /* pointer to directory dir cell */ - LINKPTR lp; /* pointer at prerequisite list */ - char *dir; /* current dir to prepend */ - char *path; /* resulting path to try to read */ - char *name; /* File name for processing a .INCLUDE */ - char *tmp; /* temporary string pointer */ - FILE *fil; /* File descriptor returned by Openfile */ + HASHPTR hp; /* pointer to macro def cell */ + CELLPTR cp; /* temporary pointer into cells list */ + CELLPTR dp; /* pointer to directory dir cell */ + LINKPTR lp; /* pointer at prerequisite list */ + char *dir; /* current dir to prepend */ + char *path; /* resulting path to try to read */ + char *name; /* File name for processing a .INCLUDE */ + char *tmp; /* temporary string pointer */ + FILE *fil; /* File descriptor returned by Openfile */ - DB_ENTER( "_do_special" ); + DB_ENTER( "_do_special" ); - target->ce_flag = F_SPECIAL; /* mark the target as special */ + target->ce_flag = F_SPECIAL; /* mark the target as special */ - switch( special ) { - case ST_EXPORT: - for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) { - DB_PRINT( "par", ("Exporting [%s]", prereq->CE_NAME) ); - hp = GET_MACRO( prereq->CE_NAME ); + switch( special ) { + case ST_EXPORT: + for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) { + DB_PRINT( "par", ("Exporting [%s]", prereq->CE_NAME) ); + hp = GET_MACRO( prereq->CE_NAME ); - if( hp != NIL(HASH) ) { - char *tmpstr = hp->ht_value; + if( hp != NIL(HASH) ) { + char *tmpstr = hp->ht_value; - if( tmpstr == NIL(char) ) tmpstr = ""; + if( tmpstr == NIL(char) ) tmpstr = ""; - if( Write_env_string( prereq->CE_NAME, tmpstr ) != 0 ) + if( Write_env_string( prereq->CE_NAME, tmpstr ) != 0 ) Warning( "Could not export %s", prereq->CE_NAME ); - } - } - break; + } + } + break; - /* Simply cause the parser to fail on the next input read */ - case ST_EXIT: - Skip_to_eof = TRUE; - break; + /* Simply cause the parser to fail on the next input read */ + case ST_EXIT: + Skip_to_eof = TRUE; + break; - case ST_IMPORT: - for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) { - char *tmpstr; + case ST_IMPORT: + for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) { + char *tmpstr; - DB_PRINT( "par", ("Importing [%s]", prereq->CE_NAME) ); + DB_PRINT( "par", ("Importing [%s]", prereq->CE_NAME) ); - if( strcmp(prereq->CE_NAME, ".EVERYTHING") == 0 ) { - t_attr sattr = Glob_attr; - Glob_attr |= A_SILENT; + if( strcmp(prereq->CE_NAME, ".EVERYTHING") == 0 ) { + t_attr sattr = Glob_attr; + Glob_attr |= A_SILENT; - ReadEnvironment(); + ReadEnvironment(); - Glob_attr = sattr; - } - else { - tmpstr = Read_env_string( prereq->CE_NAME ); + Glob_attr = sattr; + } + else { + tmpstr = Read_env_string( prereq->CE_NAME ); - if( tmpstr != NIL(char) ) + if( tmpstr != NIL(char) ) Def_macro(prereq->CE_NAME, tmpstr, M_EXPANDED|M_LITERAL); - else + else if( !((Glob_attr | attr) & A_IGNORE) ) - Fatal("Imported macro `%s' not found",prereq->CE_NAME); - } - } + Fatal("Imported macro `%s' not found",prereq->CE_NAME); + } + } - attr &= ~A_IGNORE; - break; + attr &= ~A_IGNORE; + break; - case ST_INCLUDE: - { - int pushed = FALSE; - int first = (attr & A_FIRST); - int ignore = (((Glob_attr | attr) & A_IGNORE) != 0); - int found = FALSE; - int noinf = (attr & A_NOINFER); - LINKPTR prqlnk = NIL(LINK); - LINKPTR prqlst = NIL(LINK); + case ST_INCLUDE: + { + int pushed = FALSE; + int first = (attr & A_FIRST); + int ignore = (((Glob_attr | attr) & A_IGNORE) != 0); + int found = FALSE; + int noinf = (attr & A_NOINFER); + LINKPTR prqlnk = NIL(LINK); + LINKPTR prqlst = NIL(LINK); - if( prereq == NIL(CELL) ) Fatal( "No .INCLUDE file(s) specified" ); + if( prereq == NIL(CELL) ) Fatal( "No .INCLUDE file(s) specified" ); - dp = Def_cell( ".INCLUDEDIRS" ); + dp = Def_cell( ".INCLUDEDIRS" ); - if( (attr & A_SETDIR) && *(dir = strchr(set_dir, '=')+1) ) + if( (attr & A_SETDIR) && *(dir = strchr(set_dir, '=')+1) ) pushed = Push_dir( dir, ".INCLUDE", ignore ); - for( cp=prereq; cp != NIL(CELL); cp = cp->ce_link ) { + for( cp=prereq; cp != NIL(CELL); cp = cp->ce_link ) { LINKPTR ltmp; TALLOC(ltmp, 1, LINK); ltmp->cl_prq = cp; if( prqlnk == NIL(LINK) ) - prqlst = ltmp; + prqlst = ltmp; else - prqlnk->cl_next = ltmp; + prqlnk->cl_next = ltmp; prqlnk = ltmp; - } + } - for( ; prqlst != NIL(LINK); FREE(prqlst), prqlst=prqlnk ) { + for( ; prqlst != NIL(LINK); FREE(prqlst), prqlst=prqlnk ) { prqlnk = prqlst->cl_next; cp = prqlst->cl_prq; name = cp->CE_NAME; /* Leave this here, it ensures that prqlst gets propely free'd */ if ( first && found ) - continue; + continue; if( *name == '<' ) { - /* We have a file name enclosed in <....> - * so get rid of the <> arround the file name */ + /* We have a file name enclosed in <....> + * so get rid of the <> arround the file name */ - name++; - if( (tmp = strrchr( name, '>' )) != NIL( char ) ) - *tmp = 0; + name++; + if( (tmp = strrchr( name, '>' )) != NIL( char ) ) + *tmp = 0; - if( If_root_path( name ) ) - fil = Openfile( name, FALSE, FALSE ); - else - fil = NIL(FILE); + if( If_root_path( name ) ) + fil = Openfile( name, FALSE, FALSE ); + else + fil = NIL(FILE); } else - fil = Openfile( name, FALSE, FALSE ); + fil = Openfile( name, FALSE, FALSE ); if( fil == NIL(FILE) && !If_root_path( name ) ) { /*if true ==> not found in current dir*/ - /* Now we must scan the list of prerequisites for .INCLUDEDIRS - * looking for the file in each of the specified directories. - * if we don't find it then we issue an error. The error - * message is suppressed if the .IGNORE attribute of attr is - * set. If a file is found we call Parse on the file to - * perform the parse and then continue on from where we left - * off. */ + /* Now we must scan the list of prerequisites for .INCLUDEDIRS + * looking for the file in each of the specified directories. + * if we don't find it then we issue an error. The error + * message is suppressed if the .IGNORE attribute of attr is + * set. If a file is found we call Parse on the file to + * perform the parse and then continue on from where we left + * off. */ - for(lp=dp->CE_PRQ; lp && fil == NIL(FILE); lp=lp->cl_next) { - dir = lp->cl_prq->CE_NAME; - if( strchr(dir, '$') ) dir = Expand(dir); - path = Build_path( dir, name ); + for(lp=dp->CE_PRQ; lp && fil == NIL(FILE); lp=lp->cl_next) { + dir = lp->cl_prq->CE_NAME; + if( strchr(dir, '$') ) dir = Expand(dir); + path = Build_path( dir, name ); - DB_PRINT( "par", ("Trying to include [%s]", path) ); + DB_PRINT( "par", ("Trying to include [%s]", path) ); - fil = Openfile( path, FALSE, FALSE ); - if( dir != lp->cl_prq->CE_NAME ) FREE(dir); - } + fil = Openfile( path, FALSE, FALSE ); + if( dir != lp->cl_prq->CE_NAME ) FREE(dir); + } } if (!noinf && fil == NIL(FILE)) { - t_attr glob = Glob_attr; - t_attr cattr = prqlst->cl_prq->ce_attr; + t_attr glob = Glob_attr; + t_attr cattr = prqlst->cl_prq->ce_attr; - prqlst->cl_next = NIL(LINK); - Glob_attr |= (attr&A_IGNORE); - prqlst->cl_prq->ce_attr &= ~A_FRINGE; + prqlst->cl_next = NIL(LINK); + Glob_attr |= (attr&A_IGNORE); + prqlst->cl_prq->ce_attr &= ~A_FRINGE; - if( Verbose & V_FILE_IO ) - printf( "%s: Inferring include file [%s].\n", - Pname, name ); - fil = TryFiles(prqlst); + if( Verbose & V_FILE_IO ) + printf( "%s: Inferring include file [%s].\n", + Pname, name ); + fil = TryFiles(prqlst); - Glob_attr = glob; - prqlst->cl_prq->ce_attr |= (cattr & A_FRINGE); + Glob_attr = glob; + prqlst->cl_prq->ce_attr |= (cattr & A_FRINGE); } if( fil != NIL(FILE) ) { - if( Verbose & V_FILE_IO ) - printf( "%s: Parsing include file [%s].\n", - Pname, name ); - Parse( fil ); - found = TRUE; + if( Verbose & V_FILE_IO ) + printf( "%s: Parsing include file [%s].\n", + Pname, name ); + Parse( fil ); + found = TRUE; } else if( !(ignore || first) ) - Fatal( "Include file %s, not found", name ); + Fatal( "Include file %s, not found", name ); else if( Verbose & V_FILE_IO ) - printf( "%s: Include file [%s] was not found.\n", - Pname, name ); - } + printf( "%s: Include file [%s] was not found.\n", + Pname, name ); + } - if ( !ignore && first && !found ) + if ( !ignore && first && !found ) Fatal( "No include file was found" ); - if( pushed ) Pop_dir(FALSE); - attr &= ~(A_IGNORE|A_SETDIR|A_FIRST|A_NOINFER); - } - break; + if( pushed ) Pop_dir(FALSE); + attr &= ~(A_IGNORE|A_SETDIR|A_FIRST|A_NOINFER); + } + break; + + case ST_SOURCE: + if( prereq != NIL(CELL) ) + _do_targets( op & (R_OP_CL | R_OP_MI | R_OP_UP), attr, set_dir, + target, prereq ); + else { + /* The old semantics of .SOURCE were that an empty list of + * prerequisites clears the .SOURCE list. So we must implement + * that here as a clearout prerequisite operation. Since this is + * a standard operation with the :- opcode we can simply call the + * proper routine with the target cell and it should do the trick + */ - case ST_SOURCE: - if( prereq != NIL(CELL) ) - _do_targets( op & (R_OP_CL | R_OP_MI | R_OP_UP), attr, set_dir, - target, prereq ); - else { - /* The old semantics of .SOURCE were that an empty list of - * prerequisites clears the .SOURCE list. So we must implement - * that here as a clearout prerequisite operation. Since this is - * a standard operation with the :- opcode we can simply call the - * proper routine with the target cell and it should do the trick - */ + if( op == R_OP_CL || (op & R_OP_MI) ) + Clear_prerequisites( target ); + } - if( op == R_OP_CL || (op & R_OP_MI) ) - Clear_prerequisites( target ); - } + op &= ~(R_OP_MI | R_OP_UP); + break; - op &= ~(R_OP_MI | R_OP_UP); - break; - - case ST_KEEP: - if( Keep_state != NIL(char) ) break; - Def_macro( ".KEEP_STATE", "_state.mk", M_EXPANDED ); - break; + case ST_KEEP: + if( Keep_state != NIL(char) ) break; + Def_macro( ".KEEP_STATE", "_state.mk", M_EXPANDED ); + break; - case ST_REST: - /* The rest of the special targets can all take recipes, as such they - * must be able to affect the state of the parser. */ + case ST_REST: + /* The rest of the special targets can all take recipes, as such they + * must be able to affect the state of the parser. */ - { - int s_targ = Target; + { + int s_targ = Target; - Target = TRUE; - _sp_target = TRUE; - *state = _do_targets( op, attr, set_dir, target, prereq ); - Target = s_targ; + Target = TRUE; + _sp_target = TRUE; + *state = _do_targets( op, attr, set_dir, target, prereq ); + Target = s_targ; - target->ce_flag |= F_TARGET; + target->ce_flag |= F_TARGET; - attr = A_DEFAULT; - op = R_OP_CL; - } - break; + attr = A_DEFAULT; + op = R_OP_CL; + } + break; - default:break; - } + default:break; + } - if( op != R_OP_CL ) Warning( "Modifier(s) for operator ignored" ); - if( attr != A_DEFAULT ) Warning( "Extra attributes ignored" ); + if( op != R_OP_CL ) Warning( "Modifier(s) for operator ignored" ); + if( attr != A_DEFAULT ) Warning( "Extra attributes ignored" ); - DB_VOID_RETURN; + DB_VOID_RETURN; } - static int _do_targets( op, attr, set_dir, targets, prereq )/* =================================================== diff --git a/dmake/sysintf.c b/dmake/sysintf.c index d7b482a3e405..65104114923f 100644 --- a/dmake/sysintf.c +++ b/dmake/sysintf.c @@ -420,7 +420,6 @@ char *ename; } - /* ** Set the value of the environment string ename to value. ** Returns 0 if success, non-zero if failure @@ -430,16 +429,23 @@ Write_env_string(ename, value) char *ename; char *value; { - char* p; - char* envstr = DmStrAdd(ename, value, FALSE); +#if defined(HAVE_SETENV) - p = envstr+strlen(ename); /* Don't change this code, DmStrAdd does not */ - *p++ = '='; /* add the space if *value is 0, it does */ - if( !*value ) *p = '\0'; /* allocate enough memory for one though. */ + return( setenv(ename, value, 1) ); - return( putenv(envstr) ); -} +#else /* !HAVE_SETENV */ + + char* p; + char* envstr = DmStrAdd(ename, value, FALSE); + p = envstr+strlen(ename); /* Don't change this code, DmStrAdd does not */ + *p++ = '='; /* add the space if *value is 0, it does */ + if( !*value ) *p = '\0'; /* allocate enough memory for one though. */ + + return( putenv(envstr) ); /* Possibly leaking 'envstr' */ + +#endif /* !HAVE_SETENV */ +} PUBLIC void diff --git a/dmake/unix/runargv.c b/dmake/unix/runargv.c index 4be342bbb273..e8e39d21bd3d 100644 --- a/dmake/unix/runargv.c +++ b/dmake/unix/runargv.c @@ -878,41 +878,36 @@ int wfc; /* Never change MAXPROCESS after _procs is allocated. */ if( _procs_size != Max_proc ) { - /* If procs was never initialize this is OK, do it now. */ - if( _procs == NIL(PR) ) { - _procs_size = Max_proc; - TALLOC( _procs, Max_proc, PR ); + /* If procs was never initialize this is OK, do it now. */ + if( _procs == NIL(PR) ) { + _procs_size = Max_proc; + TALLOC( _procs, Max_proc, PR ); #if defined(USE_CREATEPROCESS) - TALLOC( _wpList, Max_proc, HANDLE ); + TALLOC( _wpList, Max_proc, HANDLE ); - /* Signed int values are cast to DMHANDLE in various places, use this - * sanity check to verify that DMHANDLE is large enough. */ - if( sizeof(int) > sizeof(DMHANDLE) ) - Fatal( "Internal Error: Check type of DMHANDLE!" ); + /* Signed int values are cast to DMHANDLE in various places, use this + * sanity check to verify that DMHANDLE is large enough. */ + if( sizeof(int) > sizeof(DMHANDLE) ) + Fatal( "Internal Error: Check type of DMHANDLE!" ); #endif - } - else { - Fatal( "MAXPROCESS changed from `%d' to `%d' after a command was executed!", _procs_size, Max_proc ); - } + } + else { + Fatal( "MAXPROCESS changed from `%d' to `%d' after a command was executed!", _procs_size, Max_proc ); + } } if( Measure & M_RECIPE ) Do_profile_output( "s", M_RECIPE, target ); - /* If _use_i!=-1 then this function is called by _finished_child() - * ( through runargv() ). */ + /* If _use_i ! =-1 then this function is called by _finished_child() ( through runargv() ), + and we re-use the process queue number given by _use_i. */ if( (i = _use_i) == -1 ) { - for( i=0; ipr_valid = 1; pp->pr_pid = pid.pid; @@ -921,7 +916,9 @@ int wfc; pp->pr_ignore = ignore; pp->pr_last = last; pp->pr_wfc = wfc; - /* Freed above and after the last recipe in _finished child(). */ + + if( pp->pr_dir != NIL(char) ) + FREE(pp->pr_dir); pp->pr_dir = DmStrDup(Get_current_dir()); Current_target = NIL(CELL); @@ -953,80 +950,80 @@ _finished_child(cid, status)/* DMHANDLE cid; int status; { - register int i; - char *dir; - - if((int)cid < 1) { /* Force int. */ - /* internal command */ - i = -((int)cid); - } - else { - for( i=0; ice_attr & A_ERROR ) { - _procs[i].pr_last = TRUE; - goto ABORT_REMAINDER_OF_RECIPE; - } + if ( _procs[i].pr_target->ce_attr & A_ERROR ) { + _procs[i].pr_last = TRUE; + goto ABORT_REMAINDER_OF_RECIPE; + } - _procs[i].pr_recipe = rp->prp_next; + _procs[i].pr_recipe = rp->prp_next; - _use_i = i; - /* Run next recipe line. The rp->prp_attr propagates a possible - * wfc condition. */ - runargv( _procs[i].pr_target, rp->prp_group, - rp->prp_last, rp->prp_attr, &rp->prp_cmd ); - _use_i = -1; + _use_i = i; + /* Run next recipe line. The rp->prp_attr propagates a possible + * wfc condition. */ + runargv( _procs[i].pr_target, rp->prp_group, + rp->prp_last, rp->prp_attr, &rp->prp_cmd ); + _use_i = -1; - FREE( rp->prp_cmd ); - FREE( rp ); + FREE( rp->prp_cmd ); + FREE( rp ); - /* If all process queues are used wait for the next process to - * finish. Is this really needed here? */ - if( _proc_cnt == Max_proc ) { - Wait_for_child( FALSE, -1 ); - } - } - else { - /* empty the queue on abort. */ - if( _abort_flg ) - _procs[i].pr_recipe = NIL(RCP); + /* If all process queues are used wait for the next process to + * finish. Is this really needed here? */ + if( _proc_cnt == Max_proc ) { + Wait_for_child( FALSE, -1 ); + } + } + else { + /* empty the queue on abort. */ + if( _abort_flg ) + _procs[i].pr_recipe = NIL(RCP); - Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target); + Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target); - ABORT_REMAINDER_OF_RECIPE: - if( _procs[i].pr_last ) { - FREE(_procs[i].pr_dir ); /* Set in _add_child() */ + ABORT_REMAINDER_OF_RECIPE: + if( _procs[i].pr_last ) { + FREE(_procs[i].pr_dir ); _procs[i].pr_dir = NIL(char); /* Set in _add_child() */ - if( !Doing_bang ) { + if( !Doing_bang ) { /* Update_time_stamp() triggers the deletion of intermediate * targets. This starts a new process queue, so we have to * clear the _use_i variable. */ @@ -1035,12 +1032,12 @@ int status; _use_i = -1; Update_time_stamp( _procs[i].pr_target ); _use_i = my_use_i; - } } - } + } + } - Set_dir(dir); - FREE(dir); + Set_dir(dir); + FREE(dir); } -- cgit