1*10d63b7dSRichard Lowe /* 2*10d63b7dSRichard Lowe * CDDL HEADER START 3*10d63b7dSRichard Lowe * 4*10d63b7dSRichard Lowe * The contents of this file are subject to the terms of the 5*10d63b7dSRichard Lowe * Common Development and Distribution License (the "License"). 6*10d63b7dSRichard Lowe * You may not use this file except in compliance with the License. 7*10d63b7dSRichard Lowe * 8*10d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*10d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing. 10*10d63b7dSRichard Lowe * See the License for the specific language governing permissions 11*10d63b7dSRichard Lowe * and limitations under the License. 12*10d63b7dSRichard Lowe * 13*10d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each 14*10d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*10d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the 16*10d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying 17*10d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner] 18*10d63b7dSRichard Lowe * 19*10d63b7dSRichard Lowe * CDDL HEADER END 20*10d63b7dSRichard Lowe */ 21*10d63b7dSRichard Lowe /* 22*10d63b7dSRichard Lowe * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 23*10d63b7dSRichard Lowe * Use is subject to license terms. 24*10d63b7dSRichard Lowe */ 25*10d63b7dSRichard Lowe 26*10d63b7dSRichard Lowe /* 27*10d63b7dSRichard Lowe * implicit.c 28*10d63b7dSRichard Lowe * 29*10d63b7dSRichard Lowe * Handle suffix and percent rules 30*10d63b7dSRichard Lowe */ 31*10d63b7dSRichard Lowe 32*10d63b7dSRichard Lowe /* 33*10d63b7dSRichard Lowe * Included files 34*10d63b7dSRichard Lowe */ 35*10d63b7dSRichard Lowe #include <mk/defs.h> 36*10d63b7dSRichard Lowe #include <mksh/macro.h> /* expand_value() */ 37*10d63b7dSRichard Lowe #include <mksh/misc.h> /* retmem() */ 38*10d63b7dSRichard Lowe #include <libintl.h> 39*10d63b7dSRichard Lowe 40*10d63b7dSRichard Lowe /* 41*10d63b7dSRichard Lowe * Defined macros 42*10d63b7dSRichard Lowe */ 43*10d63b7dSRichard Lowe 44*10d63b7dSRichard Lowe /* 45*10d63b7dSRichard Lowe * typedefs & structs 46*10d63b7dSRichard Lowe */ 47*10d63b7dSRichard Lowe 48*10d63b7dSRichard Lowe /* 49*10d63b7dSRichard Lowe * Static variables 50*10d63b7dSRichard Lowe */ 51*10d63b7dSRichard Lowe static wchar_t WIDE_NULL[1] = {(wchar_t) nul_char}; 52*10d63b7dSRichard Lowe 53*10d63b7dSRichard Lowe /* 54*10d63b7dSRichard Lowe * File table of contents 55*10d63b7dSRichard Lowe */ 56*10d63b7dSRichard Lowe extern Doname find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking); 57*10d63b7dSRichard Lowe extern Doname find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking); 58*10d63b7dSRichard Lowe extern Doname find_double_suffix_rule(register Name target, Property *command, Boolean rechecking); 59*10d63b7dSRichard Lowe extern void build_suffix_list(register Name target_suffix); 60*10d63b7dSRichard Lowe extern Doname find_percent_rule(register Name target, Property *command, Boolean rechecking); 61*10d63b7dSRichard Lowe static void create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent); 62*10d63b7dSRichard Lowe static Boolean match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf); 63*10d63b7dSRichard Lowe static void construct_string_from_pattern(Percent pat_rule, String percent, String result); 64*10d63b7dSRichard Lowe static Boolean dependency_exists(Name target, Property line); 65*10d63b7dSRichard Lowe extern Property maybe_append_prop(Name, Property_id); 66*10d63b7dSRichard Lowe extern void add_target_to_chain(Name target, Chain * query); 67*10d63b7dSRichard Lowe 68*10d63b7dSRichard Lowe /* 69*10d63b7dSRichard Lowe * find_suffix_rule(target, target_body, target_suffix, command, rechecking) 70*10d63b7dSRichard Lowe * 71*10d63b7dSRichard Lowe * Does the lookup for single and double suffix rules. 72*10d63b7dSRichard Lowe * It calls build_suffix_list() to build the list of possible suffixes 73*10d63b7dSRichard Lowe * for the given target. 74*10d63b7dSRichard Lowe * It then scans the list to find the first possible source file that 75*10d63b7dSRichard Lowe * exists. This is done by concatenating the body of the target name 76*10d63b7dSRichard Lowe * (target name less target suffix) and the source suffix and checking 77*10d63b7dSRichard Lowe * if the resulting file exists. 78*10d63b7dSRichard Lowe * 79*10d63b7dSRichard Lowe * Return value: 80*10d63b7dSRichard Lowe * Indicates if search failed or not 81*10d63b7dSRichard Lowe * 82*10d63b7dSRichard Lowe * Parameters: 83*10d63b7dSRichard Lowe * target The target we need a rule for 84*10d63b7dSRichard Lowe * target_body The target name without the suffix 85*10d63b7dSRichard Lowe * target_suffix The suffix of the target 86*10d63b7dSRichard Lowe * command Pointer to slot to deposit cmd in if found 87*10d63b7dSRichard Lowe * rechecking true if we are rechecking target which depends 88*10d63b7dSRichard Lowe * on conditional macro and keep_state is set 89*10d63b7dSRichard Lowe * 90*10d63b7dSRichard Lowe * Global variables used: 91*10d63b7dSRichard Lowe * debug_level Indicates how much tracing to do 92*10d63b7dSRichard Lowe * recursion_level Used for tracing 93*10d63b7dSRichard Lowe */ 94*10d63b7dSRichard Lowe 95*10d63b7dSRichard Lowe static Boolean actual_doname = false; 96*10d63b7dSRichard Lowe 97*10d63b7dSRichard Lowe /* /tolik/ 98*10d63b7dSRichard Lowe * fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules. 99*10d63b7dSRichard Lowe * When make attemps to apply % rule it didn't look for a single suffix rule because 100*10d63b7dSRichard Lowe * if "doname" is called from "find_percent_rule" argument "implicit" is set to true 101*10d63b7dSRichard Lowe * and find_suffix_rule was not called. I've commented the checking of "implicit" 102*10d63b7dSRichard Lowe * in "doname" and make got infinite recursion for SVR4 tilde rules. 103*10d63b7dSRichard Lowe * Usage of "we_are_in_tilde" is intended to avoid this recursion. 104*10d63b7dSRichard Lowe */ 105*10d63b7dSRichard Lowe 106*10d63b7dSRichard Lowe static Boolean we_are_in_tilde = false; 107*10d63b7dSRichard Lowe 108*10d63b7dSRichard Lowe Doname 109*10d63b7dSRichard Lowe find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking) 110*10d63b7dSRichard Lowe { 111*10d63b7dSRichard Lowe static wchar_t static_string_buf_3M [ 3 * MAXPATHLEN ]; 112*10d63b7dSRichard Lowe Name true_target = target; 113*10d63b7dSRichard Lowe wchar_t *sourcename = (wchar_t*)static_string_buf_3M; 114*10d63b7dSRichard Lowe register wchar_t *put_suffix; 115*10d63b7dSRichard Lowe register Property source_suffix; 116*10d63b7dSRichard Lowe register Name source; 117*10d63b7dSRichard Lowe Doname result; 118*10d63b7dSRichard Lowe register Property line; 119*10d63b7dSRichard Lowe extern Boolean tilde_rule; 120*10d63b7dSRichard Lowe Boolean name_found = true; 121*10d63b7dSRichard Lowe Boolean posix_tilde_attempt = true; 122*10d63b7dSRichard Lowe int src_len = MAXPATHLEN + strlen(target_body->string_mb); 123*10d63b7dSRichard Lowe 124*10d63b7dSRichard Lowe /* 125*10d63b7dSRichard Lowe * To avoid infinite recursion 126*10d63b7dSRichard Lowe */ 127*10d63b7dSRichard Lowe if(we_are_in_tilde) { 128*10d63b7dSRichard Lowe we_are_in_tilde = false; 129*10d63b7dSRichard Lowe return(build_dont_know); 130*10d63b7dSRichard Lowe } 131*10d63b7dSRichard Lowe 132*10d63b7dSRichard Lowe /* 133*10d63b7dSRichard Lowe * If the target is a constructed one for a "::" target, 134*10d63b7dSRichard Lowe * we need to consider that. 135*10d63b7dSRichard Lowe */ 136*10d63b7dSRichard Lowe if (target->has_target_prop) { 137*10d63b7dSRichard Lowe true_target = get_prop(target->prop, 138*10d63b7dSRichard Lowe target_prop)->body.target.target; 139*10d63b7dSRichard Lowe } 140*10d63b7dSRichard Lowe if (debug_level > 1) { 141*10d63b7dSRichard Lowe (void) printf("%*sfind_suffix_rule(%s,%s,%s)\n", 142*10d63b7dSRichard Lowe recursion_level, 143*10d63b7dSRichard Lowe "", 144*10d63b7dSRichard Lowe true_target->string_mb, 145*10d63b7dSRichard Lowe target_body->string_mb, 146*10d63b7dSRichard Lowe target_suffix->string_mb); 147*10d63b7dSRichard Lowe } 148*10d63b7dSRichard Lowe if (command != NULL) { 149*10d63b7dSRichard Lowe if ((true_target->suffix_scan_done == true) && (*command == NULL)) { 150*10d63b7dSRichard Lowe return build_ok; 151*10d63b7dSRichard Lowe } 152*10d63b7dSRichard Lowe } 153*10d63b7dSRichard Lowe true_target->suffix_scan_done = true; 154*10d63b7dSRichard Lowe /* 155*10d63b7dSRichard Lowe * Enter all names from the directory where the target lives as 156*10d63b7dSRichard Lowe * files that makes sense. 157*10d63b7dSRichard Lowe * This will make finding the synthesized source possible. 158*10d63b7dSRichard Lowe */ 159*10d63b7dSRichard Lowe read_directory_of_file(target_body); 160*10d63b7dSRichard Lowe /* Cache the suffixes for this target suffix if not done. */ 161*10d63b7dSRichard Lowe if (!target_suffix->has_read_suffixes) { 162*10d63b7dSRichard Lowe build_suffix_list(target_suffix); 163*10d63b7dSRichard Lowe } 164*10d63b7dSRichard Lowe /* Preload the sourcename vector with the head of the target name. */ 165*10d63b7dSRichard Lowe if (src_len >= sizeof(static_string_buf_3M)) { 166*10d63b7dSRichard Lowe sourcename = ALLOC_WC(src_len); 167*10d63b7dSRichard Lowe } 168*10d63b7dSRichard Lowe (void) mbstowcs(sourcename, 169*10d63b7dSRichard Lowe target_body->string_mb, 170*10d63b7dSRichard Lowe (int) target_body->hash.length); 171*10d63b7dSRichard Lowe put_suffix = sourcename + target_body->hash.length; 172*10d63b7dSRichard Lowe /* Scan the suffix list for the target if one exists. */ 173*10d63b7dSRichard Lowe if (target_suffix->has_suffixes) { 174*10d63b7dSRichard Lowe posix_attempts: 175*10d63b7dSRichard Lowe for (source_suffix = get_prop(target_suffix->prop, 176*10d63b7dSRichard Lowe suffix_prop); 177*10d63b7dSRichard Lowe source_suffix != NULL; 178*10d63b7dSRichard Lowe source_suffix = get_prop(source_suffix->next, 179*10d63b7dSRichard Lowe suffix_prop)) { 180*10d63b7dSRichard Lowe /* Build the synthesized source name. */ 181*10d63b7dSRichard Lowe (void) mbstowcs(put_suffix, 182*10d63b7dSRichard Lowe source_suffix->body. 183*10d63b7dSRichard Lowe suffix.suffix->string_mb, 184*10d63b7dSRichard Lowe (int) source_suffix->body. 185*10d63b7dSRichard Lowe suffix.suffix->hash.length); 186*10d63b7dSRichard Lowe put_suffix[source_suffix->body. 187*10d63b7dSRichard Lowe suffix.suffix->hash.length] = 188*10d63b7dSRichard Lowe (int) nul_char; 189*10d63b7dSRichard Lowe if (debug_level > 1) { 190*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, sourcename); 191*10d63b7dSRichard Lowe (void) printf(gettext("%*sTrying %s\n"), 192*10d63b7dSRichard Lowe recursion_level, 193*10d63b7dSRichard Lowe "", 194*10d63b7dSRichard Lowe mbs_buffer); 195*10d63b7dSRichard Lowe } 196*10d63b7dSRichard Lowe source = getname_fn(sourcename, FIND_LENGTH, false, &name_found); 197*10d63b7dSRichard Lowe /* 198*10d63b7dSRichard Lowe * If the source file is not registered as 199*10d63b7dSRichard Lowe * a file, this source suffix did not match. 200*10d63b7dSRichard Lowe */ 201*10d63b7dSRichard Lowe if(vpath_defined && !posix && !svr4) { 202*10d63b7dSRichard Lowe (void) exists(source); 203*10d63b7dSRichard Lowe } 204*10d63b7dSRichard Lowe if (!source->stat.is_file) { 205*10d63b7dSRichard Lowe if(!(posix|svr4)) 206*10d63b7dSRichard Lowe { 207*10d63b7dSRichard Lowe if(!name_found) { 208*10d63b7dSRichard Lowe free_name(source); 209*10d63b7dSRichard Lowe } 210*10d63b7dSRichard Lowe continue; 211*10d63b7dSRichard Lowe } 212*10d63b7dSRichard Lowe 213*10d63b7dSRichard Lowe /* following code will ensure that the corresponding 214*10d63b7dSRichard Lowe ** tilde rules are executed when corresponding s. file 215*10d63b7dSRichard Lowe ** exists in the current directory. Though the current 216*10d63b7dSRichard Lowe ** target ends with a ~ character, there wont be any 217*10d63b7dSRichard Lowe ** any file in the current directory with that suffix 218*10d63b7dSRichard Lowe ** as it's fictitious. Even if it exists, it'll 219*10d63b7dSRichard Lowe ** execute all the rules for the ~ target. 220*10d63b7dSRichard Lowe */ 221*10d63b7dSRichard Lowe 222*10d63b7dSRichard Lowe if(source->string_mb[source->hash.length - 1] == '~' && 223*10d63b7dSRichard Lowe ( svr4 || posix_tilde_attempt ) ) 224*10d63b7dSRichard Lowe { 225*10d63b7dSRichard Lowe char *p, *np; 226*10d63b7dSRichard Lowe char *tmpbuf; 227*10d63b7dSRichard Lowe 228*10d63b7dSRichard Lowe tmpbuf = getmem(source->hash.length + 8); 229*10d63b7dSRichard Lowe /* + 8 to add "s." or "SCCS/s." */ 230*10d63b7dSRichard Lowe memset(tmpbuf,0,source->hash.length + 8); 231*10d63b7dSRichard Lowe source->string_mb[source->hash.length - 1] = '\0'; 232*10d63b7dSRichard Lowe if(p = (char *) memchr((char *)source->string_mb,'/',source->hash.length)) 233*10d63b7dSRichard Lowe { 234*10d63b7dSRichard Lowe while(1) { 235*10d63b7dSRichard Lowe if(np = (char *) memchr((char *)p+1,'/',source->hash.length - (p - source->string_mb))) { 236*10d63b7dSRichard Lowe p = np; 237*10d63b7dSRichard Lowe } else {break;} 238*10d63b7dSRichard Lowe } 239*10d63b7dSRichard Lowe /* copy everything including '/' */ 240*10d63b7dSRichard Lowe strncpy(tmpbuf, source->string_mb, p - source->string_mb + 1); 241*10d63b7dSRichard Lowe strcat(tmpbuf, "s."); 242*10d63b7dSRichard Lowe strcat(tmpbuf, p+1); 243*10d63b7dSRichard Lowe retmem((wchar_t *) source->string_mb); 244*10d63b7dSRichard Lowe source->string_mb = tmpbuf; 245*10d63b7dSRichard Lowe 246*10d63b7dSRichard Lowe } else { 247*10d63b7dSRichard Lowe strcpy(tmpbuf, "s."); 248*10d63b7dSRichard Lowe strcat(tmpbuf, source->string_mb); 249*10d63b7dSRichard Lowe retmem((wchar_t *) source->string_mb); 250*10d63b7dSRichard Lowe source->string_mb = tmpbuf; 251*10d63b7dSRichard Lowe 252*10d63b7dSRichard Lowe } 253*10d63b7dSRichard Lowe source->hash.length = strlen(source->string_mb); 254*10d63b7dSRichard Lowe if(exists(source) == file_doesnt_exist) 255*10d63b7dSRichard Lowe continue; 256*10d63b7dSRichard Lowe tilde_rule = true; 257*10d63b7dSRichard Lowe we_are_in_tilde = true; 258*10d63b7dSRichard Lowe } else { 259*10d63b7dSRichard Lowe if(!name_found) { 260*10d63b7dSRichard Lowe free_name(source); 261*10d63b7dSRichard Lowe } 262*10d63b7dSRichard Lowe continue; 263*10d63b7dSRichard Lowe } 264*10d63b7dSRichard Lowe } else { 265*10d63b7dSRichard Lowe if(posix && posix_tilde_attempt) { 266*10d63b7dSRichard Lowe if(exists(source) == file_doesnt_exist) { 267*10d63b7dSRichard Lowe if(!name_found) { 268*10d63b7dSRichard Lowe free_name(source); 269*10d63b7dSRichard Lowe } 270*10d63b7dSRichard Lowe continue; 271*10d63b7dSRichard Lowe } 272*10d63b7dSRichard Lowe } 273*10d63b7dSRichard Lowe } 274*10d63b7dSRichard Lowe 275*10d63b7dSRichard Lowe if (command != NULL) { 276*10d63b7dSRichard Lowe if(!name_found) { 277*10d63b7dSRichard Lowe store_name(source); 278*10d63b7dSRichard Lowe } 279*10d63b7dSRichard Lowe /* 280*10d63b7dSRichard Lowe * The source file is a file. 281*10d63b7dSRichard Lowe * Make sure it is up to date. 282*10d63b7dSRichard Lowe */ 283*10d63b7dSRichard Lowe if (dependency_exists(source, 284*10d63b7dSRichard Lowe get_prop(target->prop, 285*10d63b7dSRichard Lowe line_prop))) { 286*10d63b7dSRichard Lowe result = (Doname) source->state; 287*10d63b7dSRichard Lowe } else { 288*10d63b7dSRichard Lowe #if 0 /* with_squiggle sends false, which is buggy. : djay */ 289*10d63b7dSRichard Lowe result = doname(source, 290*10d63b7dSRichard Lowe (Boolean) source_suffix->body. 291*10d63b7dSRichard Lowe suffix.suffix->with_squiggle, 292*10d63b7dSRichard Lowe true); 293*10d63b7dSRichard Lowe #else 294*10d63b7dSRichard Lowe result = doname(source, 295*10d63b7dSRichard Lowe true, 296*10d63b7dSRichard Lowe true); 297*10d63b7dSRichard Lowe #endif 298*10d63b7dSRichard Lowe } 299*10d63b7dSRichard Lowe } else { 300*10d63b7dSRichard Lowe result = target_can_be_built(source); 301*10d63b7dSRichard Lowe 302*10d63b7dSRichard Lowe if (result == build_ok) { 303*10d63b7dSRichard Lowe return result; 304*10d63b7dSRichard Lowe } else { 305*10d63b7dSRichard Lowe if(!name_found) { 306*10d63b7dSRichard Lowe free_name(source); 307*10d63b7dSRichard Lowe } 308*10d63b7dSRichard Lowe continue; 309*10d63b7dSRichard Lowe } 310*10d63b7dSRichard Lowe } 311*10d63b7dSRichard Lowe 312*10d63b7dSRichard Lowe switch (result) { 313*10d63b7dSRichard Lowe case build_dont_know: 314*10d63b7dSRichard Lowe /* 315*10d63b7dSRichard Lowe * If we still can't build the source, 316*10d63b7dSRichard Lowe * this rule is not a match, 317*10d63b7dSRichard Lowe * try the next one. 318*10d63b7dSRichard Lowe */ 319*10d63b7dSRichard Lowe if (source->stat.time == file_doesnt_exist) { 320*10d63b7dSRichard Lowe if(!name_found) { 321*10d63b7dSRichard Lowe free_name(source); 322*10d63b7dSRichard Lowe } 323*10d63b7dSRichard Lowe continue; 324*10d63b7dSRichard Lowe } 325*10d63b7dSRichard Lowe case build_running: 326*10d63b7dSRichard Lowe if(!name_found) { 327*10d63b7dSRichard Lowe store_name(source); 328*10d63b7dSRichard Lowe } 329*10d63b7dSRichard Lowe true_target->suffix_scan_done = false; 330*10d63b7dSRichard Lowe line = maybe_append_prop(target, line_prop); 331*10d63b7dSRichard Lowe enter_dependency(line, source, false); 332*10d63b7dSRichard Lowe line->body.line.target = true_target; 333*10d63b7dSRichard Lowe return build_running; 334*10d63b7dSRichard Lowe case build_ok: 335*10d63b7dSRichard Lowe if(!name_found) { 336*10d63b7dSRichard Lowe store_name(source); 337*10d63b7dSRichard Lowe } 338*10d63b7dSRichard Lowe break; 339*10d63b7dSRichard Lowe case build_failed: 340*10d63b7dSRichard Lowe if(!name_found) { 341*10d63b7dSRichard Lowe store_name(source); 342*10d63b7dSRichard Lowe } 343*10d63b7dSRichard Lowe if (sourcename != static_string_buf_3M) { 344*10d63b7dSRichard Lowe retmem(sourcename); 345*10d63b7dSRichard Lowe } 346*10d63b7dSRichard Lowe return build_failed; 347*10d63b7dSRichard Lowe } 348*10d63b7dSRichard Lowe 349*10d63b7dSRichard Lowe if (debug_level > 1) { 350*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, sourcename); 351*10d63b7dSRichard Lowe (void) printf(gettext("%*sFound %s\n"), 352*10d63b7dSRichard Lowe recursion_level, 353*10d63b7dSRichard Lowe "", 354*10d63b7dSRichard Lowe mbs_buffer); 355*10d63b7dSRichard Lowe } 356*10d63b7dSRichard Lowe 357*10d63b7dSRichard Lowe if (source->depends_on_conditional) { 358*10d63b7dSRichard Lowe target->depends_on_conditional = true; 359*10d63b7dSRichard Lowe } 360*10d63b7dSRichard Lowe /* 361*10d63b7dSRichard Lowe * Since it is possible that the same target is built several times during 362*10d63b7dSRichard Lowe * the make run, we have to patch the target with all information we found 363*10d63b7dSRichard Lowe * here. Thus, the target will have an explicit rule the next time around. 364*10d63b7dSRichard Lowe */ 365*10d63b7dSRichard Lowe line = maybe_append_prop(target, line_prop); 366*10d63b7dSRichard Lowe if (*command == NULL) { 367*10d63b7dSRichard Lowe *command = line; 368*10d63b7dSRichard Lowe } 369*10d63b7dSRichard Lowe if ((source->stat.time > (*command)->body.line.dependency_time) && 370*10d63b7dSRichard Lowe (debug_level > 1)) { 371*10d63b7dSRichard Lowe (void) printf(gettext("%*sDate(%s)=%s Date-dependencies(%s)=%s\n"), 372*10d63b7dSRichard Lowe recursion_level, 373*10d63b7dSRichard Lowe "", 374*10d63b7dSRichard Lowe source->string_mb, 375*10d63b7dSRichard Lowe time_to_string(source-> 376*10d63b7dSRichard Lowe stat.time), 377*10d63b7dSRichard Lowe true_target->string_mb, 378*10d63b7dSRichard Lowe time_to_string((*command)-> 379*10d63b7dSRichard Lowe body.line. 380*10d63b7dSRichard Lowe dependency_time)); 381*10d63b7dSRichard Lowe } 382*10d63b7dSRichard Lowe /* 383*10d63b7dSRichard Lowe * Determine if this new dependency made the 384*10d63b7dSRichard Lowe * target out of date. 385*10d63b7dSRichard Lowe */ 386*10d63b7dSRichard Lowe (*command)->body.line.dependency_time = 387*10d63b7dSRichard Lowe MAX((*command)->body.line.dependency_time, 388*10d63b7dSRichard Lowe source->stat.time); 389*10d63b7dSRichard Lowe Boolean out_of_date; 390*10d63b7dSRichard Lowe if (target->is_member) { 391*10d63b7dSRichard Lowe out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, 392*10d63b7dSRichard Lowe (*command)->body.line.dependency_time); 393*10d63b7dSRichard Lowe } else { 394*10d63b7dSRichard Lowe out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, 395*10d63b7dSRichard Lowe (*command)->body.line.dependency_time); 396*10d63b7dSRichard Lowe } 397*10d63b7dSRichard Lowe if (build_unconditional || out_of_date) { 398*10d63b7dSRichard Lowe if(!rechecking) { 399*10d63b7dSRichard Lowe line->body.line.is_out_of_date = true; 400*10d63b7dSRichard Lowe } 401*10d63b7dSRichard Lowe if (debug_level > 0) { 402*10d63b7dSRichard Lowe (void) printf(gettext("%*sBuilding %s using suffix rule for %s%s because it is out of date relative to %s\n"), 403*10d63b7dSRichard Lowe recursion_level, 404*10d63b7dSRichard Lowe "", 405*10d63b7dSRichard Lowe true_target->string_mb, 406*10d63b7dSRichard Lowe source_suffix->body.suffix.suffix->string_mb, 407*10d63b7dSRichard Lowe target_suffix->string_mb, 408*10d63b7dSRichard Lowe source->string_mb); 409*10d63b7dSRichard Lowe } 410*10d63b7dSRichard Lowe } 411*10d63b7dSRichard Lowe /* 412*10d63b7dSRichard Lowe * Add the implicit rule as the target's explicit 413*10d63b7dSRichard Lowe * rule if none actually given, and register 414*10d63b7dSRichard Lowe * dependency. 415*10d63b7dSRichard Lowe * The time checking above really should be 416*10d63b7dSRichard Lowe * conditional on actual use of implicit rule 417*10d63b7dSRichard Lowe * as well. 418*10d63b7dSRichard Lowe */ 419*10d63b7dSRichard Lowe line->body.line.sccs_command = false; 420*10d63b7dSRichard Lowe if (line->body.line.command_template == NULL) { 421*10d63b7dSRichard Lowe line->body.line.command_template = 422*10d63b7dSRichard Lowe source_suffix->body.suffix.command_template; 423*10d63b7dSRichard Lowe } 424*10d63b7dSRichard Lowe enter_dependency(line, source, false); 425*10d63b7dSRichard Lowe line->body.line.target = true_target; 426*10d63b7dSRichard Lowe /* 427*10d63b7dSRichard Lowe * Also make sure the rule is built with 428*10d63b7dSRichard Lowe * $* and $< bound properly. 429*10d63b7dSRichard Lowe */ 430*10d63b7dSRichard Lowe line->body.line.star = target_body; 431*10d63b7dSRichard Lowe if(svr4|posix) { 432*10d63b7dSRichard Lowe char * p; 433*10d63b7dSRichard Lowe char tstr[256]; 434*10d63b7dSRichard Lowe extern Boolean dollarless_flag; 435*10d63b7dSRichard Lowe extern Name dollarless_value; 436*10d63b7dSRichard Lowe 437*10d63b7dSRichard Lowe if(tilde_rule) { 438*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, source->string_mb); 439*10d63b7dSRichard Lowe dollarless_value = GETNAME(wcs_buffer,FIND_LENGTH); 440*10d63b7dSRichard Lowe } 441*10d63b7dSRichard Lowe else { 442*10d63b7dSRichard Lowe dollarless_flag = false; 443*10d63b7dSRichard Lowe } 444*10d63b7dSRichard Lowe } 445*10d63b7dSRichard Lowe line->body.line.less = source; 446*10d63b7dSRichard Lowe line->body.line.percent = NULL; 447*10d63b7dSRichard Lowe add_target_to_chain(source, &(line->body.line.query)); 448*10d63b7dSRichard Lowe if (sourcename != static_string_buf_3M) { 449*10d63b7dSRichard Lowe retmem(sourcename); 450*10d63b7dSRichard Lowe } 451*10d63b7dSRichard Lowe return build_ok; 452*10d63b7dSRichard Lowe } 453*10d63b7dSRichard Lowe if(posix && posix_tilde_attempt) { 454*10d63b7dSRichard Lowe posix_tilde_attempt = false; 455*10d63b7dSRichard Lowe goto posix_attempts; 456*10d63b7dSRichard Lowe } 457*10d63b7dSRichard Lowe if ((command != NULL) && 458*10d63b7dSRichard Lowe ((*command) != NULL) && 459*10d63b7dSRichard Lowe ((*command)->body.line.star == NULL)) { 460*10d63b7dSRichard Lowe (*command)->body.line.star = target_body; 461*10d63b7dSRichard Lowe } 462*10d63b7dSRichard Lowe } 463*10d63b7dSRichard Lowe if (sourcename != static_string_buf_3M) { 464*10d63b7dSRichard Lowe retmem(sourcename); 465*10d63b7dSRichard Lowe } 466*10d63b7dSRichard Lowe /* Return here in case no rule matched the target */ 467*10d63b7dSRichard Lowe return build_dont_know; 468*10d63b7dSRichard Lowe } 469*10d63b7dSRichard Lowe 470*10d63b7dSRichard Lowe /* 471*10d63b7dSRichard Lowe * find_ar_suffix_rule(target, true_target, command, rechecking) 472*10d63b7dSRichard Lowe * 473*10d63b7dSRichard Lowe * Scans the .SUFFIXES list and tries 474*10d63b7dSRichard Lowe * to find a suffix on it that matches the tail of the target member name. 475*10d63b7dSRichard Lowe * If it finds a matching suffix it calls find_suffix_rule() to find 476*10d63b7dSRichard Lowe * a rule for the target using the suffix ".a". 477*10d63b7dSRichard Lowe * 478*10d63b7dSRichard Lowe * Return value: 479*10d63b7dSRichard Lowe * Indicates if search failed or not 480*10d63b7dSRichard Lowe * 481*10d63b7dSRichard Lowe * Parameters: 482*10d63b7dSRichard Lowe * target The target we need a rule for 483*10d63b7dSRichard Lowe * true_target The proper name 484*10d63b7dSRichard Lowe * command Pointer to slot where we stuff cmd, if found 485*10d63b7dSRichard Lowe * rechecking true if we are rechecking target which depends 486*10d63b7dSRichard Lowe * on conditional macro and keep_state is set 487*10d63b7dSRichard Lowe * 488*10d63b7dSRichard Lowe * Global variables used: 489*10d63b7dSRichard Lowe * debug_level Indicates how much tracing to do 490*10d63b7dSRichard Lowe * dot_a The Name ".a", compared against 491*10d63b7dSRichard Lowe * recursion_level Used for tracing 492*10d63b7dSRichard Lowe * suffixes List of suffixes used for scan (from .SUFFIXES) 493*10d63b7dSRichard Lowe */ 494*10d63b7dSRichard Lowe Doname 495*10d63b7dSRichard Lowe find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking) 496*10d63b7dSRichard Lowe { 497*10d63b7dSRichard Lowe wchar_t *target_end; 498*10d63b7dSRichard Lowe register Dependency suffix; 499*10d63b7dSRichard Lowe register int suffix_length; 500*10d63b7dSRichard Lowe Property line; 501*10d63b7dSRichard Lowe Name body; 502*10d63b7dSRichard Lowe static Name dot_a; 503*10d63b7dSRichard Lowe 504*10d63b7dSRichard Lowe Wstring targ_string(true_target); 505*10d63b7dSRichard Lowe Wstring suf_string; 506*10d63b7dSRichard Lowe 507*10d63b7dSRichard Lowe if (dot_a == NULL) { 508*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, ".a"); 509*10d63b7dSRichard Lowe dot_a = GETNAME(wcs_buffer, FIND_LENGTH); 510*10d63b7dSRichard Lowe } 511*10d63b7dSRichard Lowe target_end = targ_string.get_string() + true_target->hash.length; 512*10d63b7dSRichard Lowe 513*10d63b7dSRichard Lowe /* 514*10d63b7dSRichard Lowe * We compare the tail of the target name with the suffixes 515*10d63b7dSRichard Lowe * from .SUFFIXES. 516*10d63b7dSRichard Lowe */ 517*10d63b7dSRichard Lowe if (debug_level > 1) { 518*10d63b7dSRichard Lowe (void) printf("%*sfind_ar_suffix_rule(%s)\n", 519*10d63b7dSRichard Lowe recursion_level, 520*10d63b7dSRichard Lowe "", 521*10d63b7dSRichard Lowe true_target->string_mb); 522*10d63b7dSRichard Lowe } 523*10d63b7dSRichard Lowe /* 524*10d63b7dSRichard Lowe * Scan the .SUFFIXES list to see if the target matches any of 525*10d63b7dSRichard Lowe * those suffixes. 526*10d63b7dSRichard Lowe */ 527*10d63b7dSRichard Lowe for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { 528*10d63b7dSRichard Lowe /* Compare one suffix. */ 529*10d63b7dSRichard Lowe suffix_length = suffix->name->hash.length; 530*10d63b7dSRichard Lowe suf_string.init(suffix->name); 531*10d63b7dSRichard Lowe if (!IS_WEQUALN(suf_string.get_string(), 532*10d63b7dSRichard Lowe target_end - suffix_length, 533*10d63b7dSRichard Lowe suffix_length)) { 534*10d63b7dSRichard Lowe goto not_this_one; 535*10d63b7dSRichard Lowe } 536*10d63b7dSRichard Lowe /* 537*10d63b7dSRichard Lowe * The target tail matched a suffix from the .SUFFIXES list. 538*10d63b7dSRichard Lowe * Now check for a rule to match. 539*10d63b7dSRichard Lowe */ 540*10d63b7dSRichard Lowe target->suffix_scan_done = false; 541*10d63b7dSRichard Lowe body = GETNAME(targ_string.get_string(), 542*10d63b7dSRichard Lowe (int)(true_target->hash.length - 543*10d63b7dSRichard Lowe suffix_length)); 544*10d63b7dSRichard Lowe we_are_in_tilde = false; 545*10d63b7dSRichard Lowe switch (find_suffix_rule(target, 546*10d63b7dSRichard Lowe body, 547*10d63b7dSRichard Lowe dot_a, 548*10d63b7dSRichard Lowe command, 549*10d63b7dSRichard Lowe rechecking)) { 550*10d63b7dSRichard Lowe case build_ok: 551*10d63b7dSRichard Lowe line = get_prop(target->prop, line_prop); 552*10d63b7dSRichard Lowe line->body.line.star = body; 553*10d63b7dSRichard Lowe return build_ok; 554*10d63b7dSRichard Lowe case build_running: 555*10d63b7dSRichard Lowe return build_running; 556*10d63b7dSRichard Lowe } 557*10d63b7dSRichard Lowe /* 558*10d63b7dSRichard Lowe * If no rule was found, we try the next suffix to see 559*10d63b7dSRichard Lowe * if it matches the target tail, and so on. 560*10d63b7dSRichard Lowe * Go here if the suffix did not match the target tail. 561*10d63b7dSRichard Lowe */ 562*10d63b7dSRichard Lowe not_this_one:; 563*10d63b7dSRichard Lowe } 564*10d63b7dSRichard Lowe return build_dont_know; 565*10d63b7dSRichard Lowe } 566*10d63b7dSRichard Lowe 567*10d63b7dSRichard Lowe /* 568*10d63b7dSRichard Lowe * find_double_suffix_rule(target, command, rechecking) 569*10d63b7dSRichard Lowe * 570*10d63b7dSRichard Lowe * Scans the .SUFFIXES list and tries 571*10d63b7dSRichard Lowe * to find a suffix on it that matches the tail of the target name. 572*10d63b7dSRichard Lowe * If it finds a matching suffix it calls find_suffix_rule() to find 573*10d63b7dSRichard Lowe * a rule for the target. 574*10d63b7dSRichard Lowe * 575*10d63b7dSRichard Lowe * Return value: 576*10d63b7dSRichard Lowe * Indicates if scan failed or not 577*10d63b7dSRichard Lowe * 578*10d63b7dSRichard Lowe * Parameters: 579*10d63b7dSRichard Lowe * target Target we need a rule for 580*10d63b7dSRichard Lowe * command Pointer to slot where we stuff cmd, if found 581*10d63b7dSRichard Lowe * rechecking true if we are rechecking target which depends 582*10d63b7dSRichard Lowe * on conditional macro and keep_state is set 583*10d63b7dSRichard Lowe * 584*10d63b7dSRichard Lowe * Global variables used: 585*10d63b7dSRichard Lowe * debug_level Indicates how much tracing to do 586*10d63b7dSRichard Lowe * recursion_level Used for tracing 587*10d63b7dSRichard Lowe * suffixes List of suffixes used for scan (from .SUFFIXES) 588*10d63b7dSRichard Lowe */ 589*10d63b7dSRichard Lowe Doname 590*10d63b7dSRichard Lowe find_double_suffix_rule(register Name target, Property *command, Boolean rechecking) 591*10d63b7dSRichard Lowe { 592*10d63b7dSRichard Lowe Name true_target = target; 593*10d63b7dSRichard Lowe Name target_body; 594*10d63b7dSRichard Lowe register wchar_t *target_end; 595*10d63b7dSRichard Lowe register Dependency suffix; 596*10d63b7dSRichard Lowe register int suffix_length; 597*10d63b7dSRichard Lowe Boolean scanned_once = false; 598*10d63b7dSRichard Lowe Boolean name_found = true; 599*10d63b7dSRichard Lowe 600*10d63b7dSRichard Lowe Wstring targ_string; 601*10d63b7dSRichard Lowe Wstring suf_string; 602*10d63b7dSRichard Lowe 603*10d63b7dSRichard Lowe /* 604*10d63b7dSRichard Lowe * If the target is a constructed one for a "::" target, 605*10d63b7dSRichard Lowe * we need to consider that. 606*10d63b7dSRichard Lowe */ 607*10d63b7dSRichard Lowe if (target->has_target_prop) { 608*10d63b7dSRichard Lowe true_target = get_prop(target->prop, 609*10d63b7dSRichard Lowe target_prop)->body.target.target; 610*10d63b7dSRichard Lowe } 611*10d63b7dSRichard Lowe targ_string.init(true_target); 612*10d63b7dSRichard Lowe 613*10d63b7dSRichard Lowe /* 614*10d63b7dSRichard Lowe * We compare the tail of the target name with the 615*10d63b7dSRichard Lowe * suffixes from .SUFFIXES. 616*10d63b7dSRichard Lowe */ 617*10d63b7dSRichard Lowe target_end = targ_string.get_string() + true_target->hash.length; 618*10d63b7dSRichard Lowe if (debug_level > 1) { 619*10d63b7dSRichard Lowe (void) printf("%*sfind_double_suffix_rule(%s)\n", 620*10d63b7dSRichard Lowe recursion_level, 621*10d63b7dSRichard Lowe "", 622*10d63b7dSRichard Lowe true_target->string_mb); 623*10d63b7dSRichard Lowe } 624*10d63b7dSRichard Lowe /* 625*10d63b7dSRichard Lowe * Scan the .SUFFIXES list to see if the target matches 626*10d63b7dSRichard Lowe * any of those suffixes. 627*10d63b7dSRichard Lowe */ 628*10d63b7dSRichard Lowe for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { 629*10d63b7dSRichard Lowe target->suffix_scan_done = false; 630*10d63b7dSRichard Lowe true_target->suffix_scan_done = false; 631*10d63b7dSRichard Lowe /* Compare one suffix. */ 632*10d63b7dSRichard Lowe suffix_length = suffix->name->hash.length; 633*10d63b7dSRichard Lowe suf_string.init(suffix->name); 634*10d63b7dSRichard Lowe /* Check the lengths, or else RTC will report rua. */ 635*10d63b7dSRichard Lowe if (true_target->hash.length < suffix_length) { 636*10d63b7dSRichard Lowe goto not_this_one; 637*10d63b7dSRichard Lowe } else if (!IS_WEQUALN(suf_string.get_string(), 638*10d63b7dSRichard Lowe (target_end - suffix_length), 639*10d63b7dSRichard Lowe suffix_length)) { 640*10d63b7dSRichard Lowe goto not_this_one; 641*10d63b7dSRichard Lowe } 642*10d63b7dSRichard Lowe /* 643*10d63b7dSRichard Lowe * The target tail matched a suffix from the .SUFFIXES list. 644*10d63b7dSRichard Lowe * Now check for a rule to match. 645*10d63b7dSRichard Lowe */ 646*10d63b7dSRichard Lowe we_are_in_tilde = false; 647*10d63b7dSRichard Lowe target_body = GETNAME( 648*10d63b7dSRichard Lowe targ_string.get_string(), 649*10d63b7dSRichard Lowe (int)(true_target->hash.length - suffix_length) 650*10d63b7dSRichard Lowe ); 651*10d63b7dSRichard Lowe switch (find_suffix_rule(target, 652*10d63b7dSRichard Lowe target_body, 653*10d63b7dSRichard Lowe suffix->name, 654*10d63b7dSRichard Lowe command, 655*10d63b7dSRichard Lowe rechecking)) { 656*10d63b7dSRichard Lowe case build_ok: 657*10d63b7dSRichard Lowe return build_ok; 658*10d63b7dSRichard Lowe case build_running: 659*10d63b7dSRichard Lowe return build_running; 660*10d63b7dSRichard Lowe } 661*10d63b7dSRichard Lowe if (true_target->suffix_scan_done == true) { 662*10d63b7dSRichard Lowe scanned_once = true; 663*10d63b7dSRichard Lowe } 664*10d63b7dSRichard Lowe /* 665*10d63b7dSRichard Lowe * If no rule was found, we try the next suffix to see 666*10d63b7dSRichard Lowe * if it matches the target tail. And so on. 667*10d63b7dSRichard Lowe * Go here if the suffix did not match the target tail. 668*10d63b7dSRichard Lowe */ 669*10d63b7dSRichard Lowe not_this_one:; 670*10d63b7dSRichard Lowe } 671*10d63b7dSRichard Lowe if (scanned_once) 672*10d63b7dSRichard Lowe true_target->suffix_scan_done = true; 673*10d63b7dSRichard Lowe return build_dont_know; 674*10d63b7dSRichard Lowe } 675*10d63b7dSRichard Lowe 676*10d63b7dSRichard Lowe /* 677*10d63b7dSRichard Lowe * build_suffix_list(target_suffix) 678*10d63b7dSRichard Lowe * 679*10d63b7dSRichard Lowe * Scans the .SUFFIXES list and figures out 680*10d63b7dSRichard Lowe * which suffixes this target can be derived from. 681*10d63b7dSRichard Lowe * The target itself is not know here, we just know the suffix of the 682*10d63b7dSRichard Lowe * target. For each suffix on the list the target can be derived iff 683*10d63b7dSRichard Lowe * a rule exists for the name "<suffix-on-list><target-suffix>". 684*10d63b7dSRichard Lowe * A list of all possible building suffixes is built, with the rule for 685*10d63b7dSRichard Lowe * each, and tacked to the target suffix nameblock. 686*10d63b7dSRichard Lowe * 687*10d63b7dSRichard Lowe * Parameters: 688*10d63b7dSRichard Lowe * target_suffix The suffix we build a match list for 689*10d63b7dSRichard Lowe * 690*10d63b7dSRichard Lowe * Global variables used: 691*10d63b7dSRichard Lowe * debug_level Indicates how much tracing to do 692*10d63b7dSRichard Lowe * recursion_level Used for tracing 693*10d63b7dSRichard Lowe * suffixes List of suffixes used for scan (from .SUFFIXES) 694*10d63b7dSRichard Lowe * working_on_targets Indicates that this is a real target 695*10d63b7dSRichard Lowe */ 696*10d63b7dSRichard Lowe void 697*10d63b7dSRichard Lowe build_suffix_list(register Name target_suffix) 698*10d63b7dSRichard Lowe { 699*10d63b7dSRichard Lowe register Dependency source_suffix; 700*10d63b7dSRichard Lowe wchar_t rule_name[MAXPATHLEN]; 701*10d63b7dSRichard Lowe register Property line; 702*10d63b7dSRichard Lowe register Property suffix; 703*10d63b7dSRichard Lowe Name rule; 704*10d63b7dSRichard Lowe 705*10d63b7dSRichard Lowe /* If this is before default.mk has been read we just return to try */ 706*10d63b7dSRichard Lowe /* again later */ 707*10d63b7dSRichard Lowe if ((suffixes == NULL) || !working_on_targets) { 708*10d63b7dSRichard Lowe return; 709*10d63b7dSRichard Lowe } 710*10d63b7dSRichard Lowe if (debug_level > 1) { 711*10d63b7dSRichard Lowe (void) printf("%*sbuild_suffix_list(%s) ", 712*10d63b7dSRichard Lowe recursion_level, 713*10d63b7dSRichard Lowe "", 714*10d63b7dSRichard Lowe target_suffix->string_mb); 715*10d63b7dSRichard Lowe } 716*10d63b7dSRichard Lowe /* Mark the target suffix saying we cashed its list */ 717*10d63b7dSRichard Lowe target_suffix->has_read_suffixes = true; 718*10d63b7dSRichard Lowe /* Scan the .SUFFIXES list */ 719*10d63b7dSRichard Lowe for (source_suffix = suffixes; 720*10d63b7dSRichard Lowe source_suffix != NULL; 721*10d63b7dSRichard Lowe source_suffix = source_suffix->next) { 722*10d63b7dSRichard Lowe /* 723*10d63b7dSRichard Lowe * Build the name "<suffix-on-list><target-suffix>". 724*10d63b7dSRichard Lowe * (a popular one would be ".c.o"). 725*10d63b7dSRichard Lowe */ 726*10d63b7dSRichard Lowe (void) mbstowcs(rule_name, 727*10d63b7dSRichard Lowe source_suffix->name->string_mb, 728*10d63b7dSRichard Lowe (int) source_suffix->name->hash.length); 729*10d63b7dSRichard Lowe (void) mbstowcs(rule_name + source_suffix->name->hash.length, 730*10d63b7dSRichard Lowe target_suffix->string_mb, 731*10d63b7dSRichard Lowe (int) target_suffix->hash.length); 732*10d63b7dSRichard Lowe /* 733*10d63b7dSRichard Lowe * Check if that name has a rule. If not, it cannot match 734*10d63b7dSRichard Lowe * any implicit rule scan and is ignored. 735*10d63b7dSRichard Lowe * The GETNAME() call only checks for presence, it will not 736*10d63b7dSRichard Lowe * enter the name if it is not defined. 737*10d63b7dSRichard Lowe */ 738*10d63b7dSRichard Lowe if (((rule = getname_fn(rule_name, 739*10d63b7dSRichard Lowe (int) (source_suffix->name-> 740*10d63b7dSRichard Lowe hash.length + 741*10d63b7dSRichard Lowe target_suffix->hash.length), 742*10d63b7dSRichard Lowe true)) != NULL) && 743*10d63b7dSRichard Lowe ((line = get_prop(rule->prop, line_prop)) != NULL)) { 744*10d63b7dSRichard Lowe if (debug_level > 1) { 745*10d63b7dSRichard Lowe (void) printf("%s ", rule->string_mb); 746*10d63b7dSRichard Lowe } 747*10d63b7dSRichard Lowe /* 748*10d63b7dSRichard Lowe * This makes it possible to quickly determine if 749*10d63b7dSRichard Lowe * it will pay to look for a suffix property. 750*10d63b7dSRichard Lowe */ 751*10d63b7dSRichard Lowe target_suffix->has_suffixes = true; 752*10d63b7dSRichard Lowe /* 753*10d63b7dSRichard Lowe * Add the suffix property to the target suffix 754*10d63b7dSRichard Lowe * and save the rule with it. 755*10d63b7dSRichard Lowe * All information the implicit rule scanner need 756*10d63b7dSRichard Lowe * is saved in the suffix property. 757*10d63b7dSRichard Lowe */ 758*10d63b7dSRichard Lowe suffix = append_prop(target_suffix, suffix_prop); 759*10d63b7dSRichard Lowe suffix->body.suffix.suffix = source_suffix->name; 760*10d63b7dSRichard Lowe suffix->body.suffix.command_template = 761*10d63b7dSRichard Lowe line->body.line.command_template; 762*10d63b7dSRichard Lowe } 763*10d63b7dSRichard Lowe } 764*10d63b7dSRichard Lowe if (debug_level > 1) { 765*10d63b7dSRichard Lowe (void) printf("\n"); 766*10d63b7dSRichard Lowe } 767*10d63b7dSRichard Lowe } 768*10d63b7dSRichard Lowe 769*10d63b7dSRichard Lowe /* 770*10d63b7dSRichard Lowe * find_percent_rule(target, command, rechecking) 771*10d63b7dSRichard Lowe * 772*10d63b7dSRichard Lowe * Tries to find a rule from the list of wildcard matched rules. 773*10d63b7dSRichard Lowe * It scans the list attempting to match the target. 774*10d63b7dSRichard Lowe * For each target match it checks if the corresponding source exists. 775*10d63b7dSRichard Lowe * If it does the match is returned. 776*10d63b7dSRichard Lowe * The percent_list is built at makefile read time. 777*10d63b7dSRichard Lowe * Each percent rule get one entry on the list. 778*10d63b7dSRichard Lowe * 779*10d63b7dSRichard Lowe * Return value: 780*10d63b7dSRichard Lowe * Indicates if the scan failed or not 781*10d63b7dSRichard Lowe * 782*10d63b7dSRichard Lowe * Parameters: 783*10d63b7dSRichard Lowe * target The target we need a rule for 784*10d63b7dSRichard Lowe * command Pointer to slot where we stuff cmd, if found 785*10d63b7dSRichard Lowe * rechecking true if we are rechecking target which depends 786*10d63b7dSRichard Lowe * on conditional macro and keep_state is set 787*10d63b7dSRichard Lowe * 788*10d63b7dSRichard Lowe * Global variables used: 789*10d63b7dSRichard Lowe * debug_level Indicates how much tracing to do 790*10d63b7dSRichard Lowe * percent_list List of all percent rules 791*10d63b7dSRichard Lowe * recursion_level Used for tracing 792*10d63b7dSRichard Lowe * empty_name 793*10d63b7dSRichard Lowe */ 794*10d63b7dSRichard Lowe Doname 795*10d63b7dSRichard Lowe find_percent_rule(register Name target, Property *command, Boolean rechecking) 796*10d63b7dSRichard Lowe { 797*10d63b7dSRichard Lowe register Percent pat_rule, pat_depe; 798*10d63b7dSRichard Lowe register Name depe_to_check; 799*10d63b7dSRichard Lowe register Dependency depe; 800*10d63b7dSRichard Lowe register Property line; 801*10d63b7dSRichard Lowe String_rec string; 802*10d63b7dSRichard Lowe wchar_t string_buf[STRING_BUFFER_LENGTH]; 803*10d63b7dSRichard Lowe String_rec percent; 804*10d63b7dSRichard Lowe wchar_t percent_buf[STRING_BUFFER_LENGTH]; 805*10d63b7dSRichard Lowe Name true_target = target; 806*10d63b7dSRichard Lowe Name less; 807*10d63b7dSRichard Lowe Boolean nonpattern_less; 808*10d63b7dSRichard Lowe Boolean dep_name_found = false; 809*10d63b7dSRichard Lowe Doname result = build_dont_know; 810*10d63b7dSRichard Lowe Percent rule_candidate = NULL; 811*10d63b7dSRichard Lowe Boolean rule_maybe_ok; 812*10d63b7dSRichard Lowe Boolean is_pattern; 813*10d63b7dSRichard Lowe 814*10d63b7dSRichard Lowe /* If the target is constructed for a "::" target we consider that */ 815*10d63b7dSRichard Lowe if (target->has_target_prop) { 816*10d63b7dSRichard Lowe true_target = get_prop(target->prop, 817*10d63b7dSRichard Lowe target_prop)->body.target.target; 818*10d63b7dSRichard Lowe } 819*10d63b7dSRichard Lowe if (target->has_long_member_name) { 820*10d63b7dSRichard Lowe true_target = get_prop(target->prop, 821*10d63b7dSRichard Lowe long_member_name_prop)->body.long_member_name.member_name; 822*10d63b7dSRichard Lowe } 823*10d63b7dSRichard Lowe if (debug_level > 1) { 824*10d63b7dSRichard Lowe (void) printf(gettext("%*sLooking for %% rule for %s\n"), 825*10d63b7dSRichard Lowe recursion_level, 826*10d63b7dSRichard Lowe "", 827*10d63b7dSRichard Lowe true_target->string_mb); 828*10d63b7dSRichard Lowe } 829*10d63b7dSRichard Lowe for (pat_rule = percent_list; 830*10d63b7dSRichard Lowe pat_rule != NULL; 831*10d63b7dSRichard Lowe pat_rule = pat_rule->next) { 832*10d63b7dSRichard Lowe /* Avoid infinite recursion when expanding patterns */ 833*10d63b7dSRichard Lowe if (pat_rule->being_expanded == true) { 834*10d63b7dSRichard Lowe continue; 835*10d63b7dSRichard Lowe } 836*10d63b7dSRichard Lowe 837*10d63b7dSRichard Lowe /* Mark this pat_rule as "maybe ok". If no % rule is found 838*10d63b7dSRichard Lowe make will use this rule. The following algorithm is used: 839*10d63b7dSRichard Lowe 1) make scans all pattern rules in order to find the rule 840*10d63b7dSRichard Lowe where ALL dependencies, including nonpattern ones, exist or 841*10d63b7dSRichard Lowe can be built (GNU behaviour). If such rule is found make 842*10d63b7dSRichard Lowe will apply it. 843*10d63b7dSRichard Lowe 2) During this check make also remembers the first pattern rule 844*10d63b7dSRichard Lowe where all PATTERN dependencies can be build (no matter what 845*10d63b7dSRichard Lowe happens with nonpattern dependencies). 846*10d63b7dSRichard Lowe 3) If no rule satisfying 1) is found, make will apply the rule 847*10d63b7dSRichard Lowe remembered in 2) if there is one. 848*10d63b7dSRichard Lowe */ 849*10d63b7dSRichard Lowe rule_maybe_ok = true; 850*10d63b7dSRichard Lowe 851*10d63b7dSRichard Lowe /* used to track first percent dependency */ 852*10d63b7dSRichard Lowe less = NULL; 853*10d63b7dSRichard Lowe nonpattern_less = true; 854*10d63b7dSRichard Lowe 855*10d63b7dSRichard Lowe /* check whether pattern matches. 856*10d63b7dSRichard Lowe if it matches, percent string will contain matched percent part of pattern */ 857*10d63b7dSRichard Lowe if (!match_found_with_pattern(true_target, pat_rule, &percent, percent_buf)) { 858*10d63b7dSRichard Lowe continue; 859*10d63b7dSRichard Lowe } 860*10d63b7dSRichard Lowe if (pat_rule->dependencies != NULL) { 861*10d63b7dSRichard Lowe for (pat_depe = pat_rule->dependencies; 862*10d63b7dSRichard Lowe pat_depe != NULL; 863*10d63b7dSRichard Lowe pat_depe = pat_depe->next) { 864*10d63b7dSRichard Lowe /* checking result for dependency */ 865*10d63b7dSRichard Lowe result = build_dont_know; 866*10d63b7dSRichard Lowe 867*10d63b7dSRichard Lowe dep_name_found = true; 868*10d63b7dSRichard Lowe if (pat_depe->name->percent) { 869*10d63b7dSRichard Lowe is_pattern = true; 870*10d63b7dSRichard Lowe /* build dependency name */ 871*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 872*10d63b7dSRichard Lowe construct_string_from_pattern(pat_depe, &percent, &string); 873*10d63b7dSRichard Lowe depe_to_check = getname_fn(string.buffer.start, 874*10d63b7dSRichard Lowe FIND_LENGTH, 875*10d63b7dSRichard Lowe false, 876*10d63b7dSRichard Lowe &dep_name_found 877*10d63b7dSRichard Lowe ); 878*10d63b7dSRichard Lowe 879*10d63b7dSRichard Lowe if ((less == NULL) || nonpattern_less) { 880*10d63b7dSRichard Lowe less = depe_to_check; 881*10d63b7dSRichard Lowe nonpattern_less = false; 882*10d63b7dSRichard Lowe } 883*10d63b7dSRichard Lowe } else { 884*10d63b7dSRichard Lowe /* nonpattern dependency */ 885*10d63b7dSRichard Lowe is_pattern = false; 886*10d63b7dSRichard Lowe depe_to_check = pat_depe->name; 887*10d63b7dSRichard Lowe if(depe_to_check->dollar) { 888*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 889*10d63b7dSRichard Lowe expand_value(depe_to_check, &string, false); 890*10d63b7dSRichard Lowe depe_to_check = getname_fn(string.buffer.start, 891*10d63b7dSRichard Lowe FIND_LENGTH, 892*10d63b7dSRichard Lowe false, 893*10d63b7dSRichard Lowe &dep_name_found 894*10d63b7dSRichard Lowe ); 895*10d63b7dSRichard Lowe } 896*10d63b7dSRichard Lowe if (less == NULL) { 897*10d63b7dSRichard Lowe less = depe_to_check; 898*10d63b7dSRichard Lowe } 899*10d63b7dSRichard Lowe } 900*10d63b7dSRichard Lowe 901*10d63b7dSRichard Lowe if (depe_to_check == empty_name) { 902*10d63b7dSRichard Lowe result = build_ok; 903*10d63b7dSRichard Lowe } else { 904*10d63b7dSRichard Lowe if (debug_level > 1) { 905*10d63b7dSRichard Lowe (void) printf(gettext("%*sTrying %s\n"), 906*10d63b7dSRichard Lowe recursion_level, 907*10d63b7dSRichard Lowe "", 908*10d63b7dSRichard Lowe depe_to_check->string_mb); 909*10d63b7dSRichard Lowe } 910*10d63b7dSRichard Lowe 911*10d63b7dSRichard Lowe pat_rule->being_expanded = true; 912*10d63b7dSRichard Lowe 913*10d63b7dSRichard Lowe /* suppress message output */ 914*10d63b7dSRichard Lowe int save_debug_level = debug_level; 915*10d63b7dSRichard Lowe debug_level = 0; 916*10d63b7dSRichard Lowe 917*10d63b7dSRichard Lowe /* check whether dependency can be built */ 918*10d63b7dSRichard Lowe if (dependency_exists(depe_to_check, 919*10d63b7dSRichard Lowe get_prop(target->prop, 920*10d63b7dSRichard Lowe line_prop))) 921*10d63b7dSRichard Lowe { 922*10d63b7dSRichard Lowe result = (Doname) depe_to_check->state; 923*10d63b7dSRichard Lowe } else { 924*10d63b7dSRichard Lowe if(actual_doname) { 925*10d63b7dSRichard Lowe result = doname(depe_to_check, true, true); 926*10d63b7dSRichard Lowe } else { 927*10d63b7dSRichard Lowe result = target_can_be_built(depe_to_check); 928*10d63b7dSRichard Lowe } 929*10d63b7dSRichard Lowe if(!dep_name_found) { 930*10d63b7dSRichard Lowe if(result != build_ok && result != build_running) { 931*10d63b7dSRichard Lowe free_name(depe_to_check); 932*10d63b7dSRichard Lowe } else { 933*10d63b7dSRichard Lowe store_name(depe_to_check); 934*10d63b7dSRichard Lowe } 935*10d63b7dSRichard Lowe } 936*10d63b7dSRichard Lowe } 937*10d63b7dSRichard Lowe if(result != build_ok && is_pattern) { 938*10d63b7dSRichard Lowe rule_maybe_ok = false; 939*10d63b7dSRichard Lowe } 940*10d63b7dSRichard Lowe 941*10d63b7dSRichard Lowe /* restore debug_level */ 942*10d63b7dSRichard Lowe debug_level = save_debug_level; 943*10d63b7dSRichard Lowe } 944*10d63b7dSRichard Lowe 945*10d63b7dSRichard Lowe if (pat_depe->name->percent) { 946*10d63b7dSRichard Lowe if (string.free_after_use) { 947*10d63b7dSRichard Lowe retmem(string.buffer.start); 948*10d63b7dSRichard Lowe } 949*10d63b7dSRichard Lowe } 950*10d63b7dSRichard Lowe /* make can't figure out how to make this dependency */ 951*10d63b7dSRichard Lowe if (result != build_ok && result != build_running) { 952*10d63b7dSRichard Lowe pat_rule->being_expanded = false; 953*10d63b7dSRichard Lowe break; 954*10d63b7dSRichard Lowe } 955*10d63b7dSRichard Lowe } 956*10d63b7dSRichard Lowe } else { 957*10d63b7dSRichard Lowe result = build_ok; 958*10d63b7dSRichard Lowe } 959*10d63b7dSRichard Lowe 960*10d63b7dSRichard Lowe /* this pattern rule is the needed one since all dependencies could be built */ 961*10d63b7dSRichard Lowe if (result == build_ok || result == build_running) { 962*10d63b7dSRichard Lowe break; 963*10d63b7dSRichard Lowe } 964*10d63b7dSRichard Lowe 965*10d63b7dSRichard Lowe /* Make does not know how to build some of dependencies from this rule. 966*10d63b7dSRichard Lowe But if all "pattern" dependencies can be built, we remember this rule 967*10d63b7dSRichard Lowe as a candidate for the case if no other pattern rule found. 968*10d63b7dSRichard Lowe */ 969*10d63b7dSRichard Lowe if(rule_maybe_ok && rule_candidate == NULL) { 970*10d63b7dSRichard Lowe rule_candidate = pat_rule; 971*10d63b7dSRichard Lowe } 972*10d63b7dSRichard Lowe } 973*10d63b7dSRichard Lowe 974*10d63b7dSRichard Lowe /* if no pattern matching rule was found, use the remembered candidate 975*10d63b7dSRichard Lowe or return build_dont_know if there is no candidate. 976*10d63b7dSRichard Lowe */ 977*10d63b7dSRichard Lowe if (result != build_ok && result != build_running) { 978*10d63b7dSRichard Lowe if(rule_candidate) { 979*10d63b7dSRichard Lowe pat_rule = rule_candidate; 980*10d63b7dSRichard Lowe } else { 981*10d63b7dSRichard Lowe return build_dont_know; 982*10d63b7dSRichard Lowe } 983*10d63b7dSRichard Lowe } 984*10d63b7dSRichard Lowe 985*10d63b7dSRichard Lowe /* if we are performing only check whether dependency could be built with existing rules, 986*10d63b7dSRichard Lowe return success */ 987*10d63b7dSRichard Lowe if (command == NULL) { 988*10d63b7dSRichard Lowe if(pat_rule != NULL) { 989*10d63b7dSRichard Lowe pat_rule->being_expanded = false; 990*10d63b7dSRichard Lowe } 991*10d63b7dSRichard Lowe return result; 992*10d63b7dSRichard Lowe } 993*10d63b7dSRichard Lowe 994*10d63b7dSRichard Lowe if (debug_level > 1) { 995*10d63b7dSRichard Lowe (void) printf(gettext("%*sMatched %s:"), 996*10d63b7dSRichard Lowe recursion_level, 997*10d63b7dSRichard Lowe "", 998*10d63b7dSRichard Lowe target->string_mb); 999*10d63b7dSRichard Lowe 1000*10d63b7dSRichard Lowe for (pat_depe = pat_rule->dependencies; 1001*10d63b7dSRichard Lowe pat_depe != NULL; 1002*10d63b7dSRichard Lowe pat_depe = pat_depe->next) { 1003*10d63b7dSRichard Lowe if (pat_depe->name->percent) { 1004*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1005*10d63b7dSRichard Lowe construct_string_from_pattern(pat_depe, &percent, &string); 1006*10d63b7dSRichard Lowe depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH); 1007*10d63b7dSRichard Lowe } else { 1008*10d63b7dSRichard Lowe depe_to_check = pat_depe->name; 1009*10d63b7dSRichard Lowe if(depe_to_check->dollar) { 1010*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1011*10d63b7dSRichard Lowe expand_value(depe_to_check, &string, false); 1012*10d63b7dSRichard Lowe depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH); 1013*10d63b7dSRichard Lowe } 1014*10d63b7dSRichard Lowe } 1015*10d63b7dSRichard Lowe 1016*10d63b7dSRichard Lowe if (depe_to_check != empty_name) { 1017*10d63b7dSRichard Lowe (void) printf(" %s", depe_to_check->string_mb); 1018*10d63b7dSRichard Lowe } 1019*10d63b7dSRichard Lowe } 1020*10d63b7dSRichard Lowe 1021*10d63b7dSRichard Lowe (void) printf(gettext(" from: %s:"), 1022*10d63b7dSRichard Lowe pat_rule->name->string_mb); 1023*10d63b7dSRichard Lowe 1024*10d63b7dSRichard Lowe for (pat_depe = pat_rule->dependencies; 1025*10d63b7dSRichard Lowe pat_depe != NULL; 1026*10d63b7dSRichard Lowe pat_depe = pat_depe->next) { 1027*10d63b7dSRichard Lowe (void) printf(" %s", pat_depe->name->string_mb); 1028*10d63b7dSRichard Lowe } 1029*10d63b7dSRichard Lowe 1030*10d63b7dSRichard Lowe (void) printf("\n"); 1031*10d63b7dSRichard Lowe } 1032*10d63b7dSRichard Lowe 1033*10d63b7dSRichard Lowe if (true_target->colons == no_colon) { 1034*10d63b7dSRichard Lowe true_target->colons = one_colon; 1035*10d63b7dSRichard Lowe } 1036*10d63b7dSRichard Lowe 1037*10d63b7dSRichard Lowe /* create deppendency list and target group from matched pattern rule */ 1038*10d63b7dSRichard Lowe create_target_group_and_dependencies_list(target, pat_rule, &percent); 1039*10d63b7dSRichard Lowe 1040*10d63b7dSRichard Lowe /* save command */ 1041*10d63b7dSRichard Lowe line = get_prop(target->prop, line_prop); 1042*10d63b7dSRichard Lowe *command = line; 1043*10d63b7dSRichard Lowe 1044*10d63b7dSRichard Lowe /* free query chain if one exist */ 1045*10d63b7dSRichard Lowe while(line->body.line.query != NULL) { 1046*10d63b7dSRichard Lowe Chain to_free = line->body.line.query; 1047*10d63b7dSRichard Lowe line->body.line.query = line->body.line.query->next; 1048*10d63b7dSRichard Lowe retmem_mb((char *) to_free); 1049*10d63b7dSRichard Lowe } 1050*10d63b7dSRichard Lowe 1051*10d63b7dSRichard Lowe if (line->body.line.dependencies != NULL) { 1052*10d63b7dSRichard Lowe /* build all collected dependencies */ 1053*10d63b7dSRichard Lowe for (depe = line->body.line.dependencies; 1054*10d63b7dSRichard Lowe depe != NULL; 1055*10d63b7dSRichard Lowe depe = depe->next) { 1056*10d63b7dSRichard Lowe actual_doname = true; 1057*10d63b7dSRichard Lowe result = doname_check(depe->name, true, true, depe->automatic); 1058*10d63b7dSRichard Lowe 1059*10d63b7dSRichard Lowe actual_doname = false; 1060*10d63b7dSRichard Lowe if (result == build_failed) { 1061*10d63b7dSRichard Lowe pat_rule->being_expanded = false; 1062*10d63b7dSRichard Lowe return build_failed; 1063*10d63b7dSRichard Lowe } 1064*10d63b7dSRichard Lowe if (result == build_running) { 1065*10d63b7dSRichard Lowe pat_rule->being_expanded = false; 1066*10d63b7dSRichard Lowe return build_running; 1067*10d63b7dSRichard Lowe } 1068*10d63b7dSRichard Lowe 1069*10d63b7dSRichard Lowe if ((depe->name->stat.time > line->body.line.dependency_time) && 1070*10d63b7dSRichard Lowe (debug_level > 1)) { 1071*10d63b7dSRichard Lowe (void) printf(gettext("%*sDate(%s)=%s Date-dependencies(%s)=%s\n"), 1072*10d63b7dSRichard Lowe recursion_level, 1073*10d63b7dSRichard Lowe "", 1074*10d63b7dSRichard Lowe depe->name->string_mb, 1075*10d63b7dSRichard Lowe time_to_string(depe->name->stat.time), 1076*10d63b7dSRichard Lowe true_target->string_mb, 1077*10d63b7dSRichard Lowe time_to_string(line->body.line.dependency_time)); 1078*10d63b7dSRichard Lowe } 1079*10d63b7dSRichard Lowe 1080*10d63b7dSRichard Lowe line->body.line.dependency_time = 1081*10d63b7dSRichard Lowe MAX(line->body.line.dependency_time, depe->name->stat.time); 1082*10d63b7dSRichard Lowe 1083*10d63b7dSRichard Lowe /* determine whether this dependency made target out of date */ 1084*10d63b7dSRichard Lowe Boolean out_of_date; 1085*10d63b7dSRichard Lowe if (target->is_member || depe->name->is_member) { 1086*10d63b7dSRichard Lowe out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, depe->name->stat.time); 1087*10d63b7dSRichard Lowe } else { 1088*10d63b7dSRichard Lowe out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, depe->name->stat.time); 1089*10d63b7dSRichard Lowe } 1090*10d63b7dSRichard Lowe if (build_unconditional || out_of_date) { 1091*10d63b7dSRichard Lowe if(!rechecking) { 1092*10d63b7dSRichard Lowe line->body.line.is_out_of_date = true; 1093*10d63b7dSRichard Lowe } 1094*10d63b7dSRichard Lowe add_target_to_chain(depe->name, &(line->body.line.query)); 1095*10d63b7dSRichard Lowe 1096*10d63b7dSRichard Lowe if (debug_level > 0) { 1097*10d63b7dSRichard Lowe (void) printf(gettext("%*sBuilding %s using pattern rule %s:"), 1098*10d63b7dSRichard Lowe recursion_level, 1099*10d63b7dSRichard Lowe "", 1100*10d63b7dSRichard Lowe true_target->string_mb, 1101*10d63b7dSRichard Lowe pat_rule->name->string_mb); 1102*10d63b7dSRichard Lowe 1103*10d63b7dSRichard Lowe for (pat_depe = pat_rule->dependencies; 1104*10d63b7dSRichard Lowe pat_depe != NULL; 1105*10d63b7dSRichard Lowe pat_depe = pat_depe->next) { 1106*10d63b7dSRichard Lowe (void) printf(" %s", pat_depe->name->string_mb); 1107*10d63b7dSRichard Lowe } 1108*10d63b7dSRichard Lowe 1109*10d63b7dSRichard Lowe (void) printf(gettext(" because it is out of date relative to %s\n"), 1110*10d63b7dSRichard Lowe depe->name->string_mb); 1111*10d63b7dSRichard Lowe } 1112*10d63b7dSRichard Lowe } 1113*10d63b7dSRichard Lowe } 1114*10d63b7dSRichard Lowe } else { 1115*10d63b7dSRichard Lowe if ((true_target->stat.time <= file_doesnt_exist) || 1116*10d63b7dSRichard Lowe (true_target->stat.time < line->body.line.dependency_time)) { 1117*10d63b7dSRichard Lowe if(!rechecking) { 1118*10d63b7dSRichard Lowe line->body.line.is_out_of_date = true; 1119*10d63b7dSRichard Lowe } 1120*10d63b7dSRichard Lowe if (debug_level > 0) { 1121*10d63b7dSRichard Lowe (void) printf(gettext("%*sBuilding %s using pattern rule %s: "), 1122*10d63b7dSRichard Lowe recursion_level, 1123*10d63b7dSRichard Lowe "", 1124*10d63b7dSRichard Lowe true_target->string_mb, 1125*10d63b7dSRichard Lowe pat_rule->name->string_mb, 1126*10d63b7dSRichard Lowe (target->stat.time > file_doesnt_exist) ? 1127*10d63b7dSRichard Lowe gettext("because it is out of date") : 1128*10d63b7dSRichard Lowe gettext("because it does not exist")); 1129*10d63b7dSRichard Lowe } 1130*10d63b7dSRichard Lowe } 1131*10d63b7dSRichard Lowe } 1132*10d63b7dSRichard Lowe 1133*10d63b7dSRichard Lowe /* enter explicit rule from percent rule */ 1134*10d63b7dSRichard Lowe Name lmn_target = true_target; 1135*10d63b7dSRichard Lowe if (true_target->has_long_member_name) { 1136*10d63b7dSRichard Lowe lmn_target = get_prop(true_target->prop, long_member_name_prop)->body.long_member_name.member_name; 1137*10d63b7dSRichard Lowe } 1138*10d63b7dSRichard Lowe line->body.line.sccs_command = false; 1139*10d63b7dSRichard Lowe line->body.line.target = true_target; 1140*10d63b7dSRichard Lowe line->body.line.command_template = pat_rule->command_template; 1141*10d63b7dSRichard Lowe line->body.line.star = GETNAME(percent.buffer.start, FIND_LENGTH); 1142*10d63b7dSRichard Lowe line->body.line.less = less; 1143*10d63b7dSRichard Lowe 1144*10d63b7dSRichard Lowe if (lmn_target->parenleft) { 1145*10d63b7dSRichard Lowe Wstring lmn_string(lmn_target); 1146*10d63b7dSRichard Lowe 1147*10d63b7dSRichard Lowe wchar_t *left = (wchar_t *) wcschr(lmn_string.get_string(), (int) parenleft_char); 1148*10d63b7dSRichard Lowe wchar_t *right = (wchar_t *) wcschr(lmn_string.get_string(), (int) parenright_char); 1149*10d63b7dSRichard Lowe 1150*10d63b7dSRichard Lowe if ((left == NULL) || (right == NULL)) { 1151*10d63b7dSRichard Lowe line->body.line.percent = NULL; 1152*10d63b7dSRichard Lowe } else { 1153*10d63b7dSRichard Lowe line->body.line.percent = GETNAME(left + 1, right - left - 1); 1154*10d63b7dSRichard Lowe } 1155*10d63b7dSRichard Lowe } else { 1156*10d63b7dSRichard Lowe line->body.line.percent = NULL; 1157*10d63b7dSRichard Lowe } 1158*10d63b7dSRichard Lowe pat_rule->being_expanded = false; 1159*10d63b7dSRichard Lowe 1160*10d63b7dSRichard Lowe return result; 1161*10d63b7dSRichard Lowe } 1162*10d63b7dSRichard Lowe 1163*10d63b7dSRichard Lowe /* 1164*10d63b7dSRichard Lowe * match_found_with_pattern 1165*10d63b7dSRichard Lowe * ( target, pat_rule, percent, percent_buf) 1166*10d63b7dSRichard Lowe * 1167*10d63b7dSRichard Lowe * matches "target->string" with a % pattern. 1168*10d63b7dSRichard Lowe * If pattern contains a MACRO definition, it's expanded first. 1169*10d63b7dSRichard Lowe * 1170*10d63b7dSRichard Lowe * Return value: 1171*10d63b7dSRichard Lowe * true if a match was found 1172*10d63b7dSRichard Lowe * 1173*10d63b7dSRichard Lowe * Parameters: 1174*10d63b7dSRichard Lowe * target The target we're trying to match 1175*10d63b7dSRichard Lowe * pattern 1176*10d63b7dSRichard Lowe * percent record that contains "percent_buf" below 1177*10d63b7dSRichard Lowe * percent_buf This is where the patched % part of pattern is stored 1178*10d63b7dSRichard Lowe * 1179*10d63b7dSRichard Lowe */ 1180*10d63b7dSRichard Lowe 1181*10d63b7dSRichard Lowe static Boolean 1182*10d63b7dSRichard Lowe match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf) { 1183*10d63b7dSRichard Lowe String_rec string; 1184*10d63b7dSRichard Lowe wchar_t string_buf[STRING_BUFFER_LENGTH]; 1185*10d63b7dSRichard Lowe 1186*10d63b7dSRichard Lowe /* construct prefix string and check whether prefix matches */ 1187*10d63b7dSRichard Lowe Name prefix = pat_rule->patterns[0]; 1188*10d63b7dSRichard Lowe int prefix_length; 1189*10d63b7dSRichard Lowe 1190*10d63b7dSRichard Lowe Wstring targ_string(target); 1191*10d63b7dSRichard Lowe Wstring pref_string(prefix); 1192*10d63b7dSRichard Lowe Wstring suf_string; 1193*10d63b7dSRichard Lowe 1194*10d63b7dSRichard Lowe if (prefix->dollar) { 1195*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1196*10d63b7dSRichard Lowe expand_value(prefix, &string, false); 1197*10d63b7dSRichard Lowe prefix_length = string.text.p - string.buffer.start; 1198*10d63b7dSRichard Lowe if ((string.buffer.start[0] == (int) period_char) && 1199*10d63b7dSRichard Lowe (string.buffer.start[1] == (int) slash_char)) { 1200*10d63b7dSRichard Lowe string.buffer.start += 2; 1201*10d63b7dSRichard Lowe prefix_length -= 2; 1202*10d63b7dSRichard Lowe } 1203*10d63b7dSRichard Lowe if (!targ_string.equaln(string.buffer.start, prefix_length)) { 1204*10d63b7dSRichard Lowe return false; 1205*10d63b7dSRichard Lowe } 1206*10d63b7dSRichard Lowe } else { 1207*10d63b7dSRichard Lowe prefix_length = prefix->hash.length; 1208*10d63b7dSRichard Lowe if (!targ_string.equaln(&pref_string, prefix_length)) { 1209*10d63b7dSRichard Lowe return false; 1210*10d63b7dSRichard Lowe } 1211*10d63b7dSRichard Lowe } 1212*10d63b7dSRichard Lowe 1213*10d63b7dSRichard Lowe /* do the same with pattern suffix */ 1214*10d63b7dSRichard Lowe Name suffix = pat_rule->patterns[pat_rule->patterns_total - 1]; 1215*10d63b7dSRichard Lowe suf_string.init(suffix); 1216*10d63b7dSRichard Lowe 1217*10d63b7dSRichard Lowe int suffix_length; 1218*10d63b7dSRichard Lowe if (suffix->dollar) { 1219*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1220*10d63b7dSRichard Lowe expand_value(suffix, &string, false); 1221*10d63b7dSRichard Lowe suffix_length = string.text.p - string.buffer.start; 1222*10d63b7dSRichard Lowe if(suffix_length > target->hash.length) { 1223*10d63b7dSRichard Lowe return false; 1224*10d63b7dSRichard Lowe } 1225*10d63b7dSRichard Lowe if (!targ_string.equal(string.buffer.start, target->hash.length - suffix_length)) { 1226*10d63b7dSRichard Lowe return false; 1227*10d63b7dSRichard Lowe } 1228*10d63b7dSRichard Lowe } else { 1229*10d63b7dSRichard Lowe suffix_length = (int) suffix->hash.length; 1230*10d63b7dSRichard Lowe if(suffix_length > target->hash.length) { 1231*10d63b7dSRichard Lowe return false; 1232*10d63b7dSRichard Lowe } 1233*10d63b7dSRichard Lowe if (!targ_string.equal(&suf_string, target->hash.length - suffix_length)) { 1234*10d63b7dSRichard Lowe return false; 1235*10d63b7dSRichard Lowe } 1236*10d63b7dSRichard Lowe } 1237*10d63b7dSRichard Lowe 1238*10d63b7dSRichard Lowe Boolean match_found = false; 1239*10d63b7dSRichard Lowe int percent_length = target->hash.length - prefix_length - suffix_length; 1240*10d63b7dSRichard Lowe 1241*10d63b7dSRichard Lowe while (!match_found && (percent_length >= 0)) { 1242*10d63b7dSRichard Lowe /* init result string */ 1243*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1244*10d63b7dSRichard Lowe 1245*10d63b7dSRichard Lowe /* init percent string */ 1246*10d63b7dSRichard Lowe percent->buffer.start = percent_buf; 1247*10d63b7dSRichard Lowe percent->text.p = percent_buf; 1248*10d63b7dSRichard Lowe percent->text.end = NULL; 1249*10d63b7dSRichard Lowe percent->free_after_use = false; 1250*10d63b7dSRichard Lowe percent->buffer.end = percent_buf + STRING_BUFFER_LENGTH; 1251*10d63b7dSRichard Lowe 1252*10d63b7dSRichard Lowe /* construct percent and result strings */ 1253*10d63b7dSRichard Lowe targ_string.append_to_str(percent, prefix_length, percent_length); 1254*10d63b7dSRichard Lowe construct_string_from_pattern(pat_rule, percent, &string); 1255*10d63b7dSRichard Lowe 1256*10d63b7dSRichard Lowe /* check for match */ 1257*10d63b7dSRichard Lowe if (targ_string.equal(string.buffer.start, 0)) { 1258*10d63b7dSRichard Lowe match_found = true; 1259*10d63b7dSRichard Lowe } else { 1260*10d63b7dSRichard Lowe percent_length--; 1261*10d63b7dSRichard Lowe } 1262*10d63b7dSRichard Lowe } 1263*10d63b7dSRichard Lowe 1264*10d63b7dSRichard Lowe /* result */ 1265*10d63b7dSRichard Lowe return match_found; 1266*10d63b7dSRichard Lowe } 1267*10d63b7dSRichard Lowe 1268*10d63b7dSRichard Lowe 1269*10d63b7dSRichard Lowe /* 1270*10d63b7dSRichard Lowe * create_target_group_and_dependencies_list 1271*10d63b7dSRichard Lowe * (target, pat_rule, percent) 1272*10d63b7dSRichard Lowe * 1273*10d63b7dSRichard Lowe * constructs dependency list and a target group from pattern. 1274*10d63b7dSRichard Lowe * 1275*10d63b7dSRichard Lowe * If we have the lines 1276*10d63b7dSRichard Lowe * %/%.a + %/%.b + C%/CC%.c: yyy %.d bb%/BB%.e 1277*10d63b7dSRichard Lowe * commands 1278*10d63b7dSRichard Lowe * 1279*10d63b7dSRichard Lowe * and we have matched the pattern xx/xx.a with %/%.a, then we 1280*10d63b7dSRichard Lowe * construct a target group that looks like this: 1281*10d63b7dSRichard Lowe * xx/xx.a + xx/xx.b + Cxx/CCxx.c: dependencies 1282*10d63b7dSRichard Lowe * 1283*10d63b7dSRichard Lowe * and construct dependency list that looks like this: 1284*10d63b7dSRichard Lowe * yyy xx.d bbxx/BBxx.e + already existed dependencies 1285*10d63b7dSRichard Lowe * 1286*10d63b7dSRichard Lowe * Return value: 1287*10d63b7dSRichard Lowe * none 1288*10d63b7dSRichard Lowe * 1289*10d63b7dSRichard Lowe * Parameters: 1290*10d63b7dSRichard Lowe * target The target we are building, in the previous 1291*10d63b7dSRichard Lowe * example, this is xx/xx.a 1292*10d63b7dSRichard Lowe * pat_rule the % pattern that matched "target", here %/%.a 1293*10d63b7dSRichard Lowe * percent string containing matched % part. In the example=xx. 1294*10d63b7dSRichard Lowe * 1295*10d63b7dSRichard Lowe * Global variables used: 1296*10d63b7dSRichard Lowe * empty_name 1297*10d63b7dSRichard Lowe */ 1298*10d63b7dSRichard Lowe 1299*10d63b7dSRichard Lowe static void 1300*10d63b7dSRichard Lowe create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent) { 1301*10d63b7dSRichard Lowe String_rec string; 1302*10d63b7dSRichard Lowe wchar_t string_buf[STRING_BUFFER_LENGTH]; 1303*10d63b7dSRichard Lowe Percent pat_depe; 1304*10d63b7dSRichard Lowe Name depe; 1305*10d63b7dSRichard Lowe Property line = maybe_append_prop(target, line_prop); 1306*10d63b7dSRichard Lowe Chain new_target_group = NULL; 1307*10d63b7dSRichard Lowe Chain *new_target_group_tail = &new_target_group; 1308*10d63b7dSRichard Lowe Chain group_member; 1309*10d63b7dSRichard Lowe 1310*10d63b7dSRichard Lowe /* create and append dependencies from rule */ 1311*10d63b7dSRichard Lowe for (pat_depe = pat_rule->dependencies; pat_depe != NULL; pat_depe = pat_depe->next) { 1312*10d63b7dSRichard Lowe if (pat_depe->name->percent) { 1313*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1314*10d63b7dSRichard Lowe construct_string_from_pattern(pat_depe, percent, &string); 1315*10d63b7dSRichard Lowe depe = GETNAME(string.buffer.start, FIND_LENGTH); 1316*10d63b7dSRichard Lowe if (depe != empty_name) { 1317*10d63b7dSRichard Lowe enter_dependency(line, depe, false); 1318*10d63b7dSRichard Lowe } 1319*10d63b7dSRichard Lowe } else { 1320*10d63b7dSRichard Lowe depe = pat_depe->name; 1321*10d63b7dSRichard Lowe if(depe->dollar) { 1322*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1323*10d63b7dSRichard Lowe expand_value(depe, &string, false); 1324*10d63b7dSRichard Lowe depe = GETNAME(string.buffer.start, FIND_LENGTH); 1325*10d63b7dSRichard Lowe } 1326*10d63b7dSRichard Lowe enter_dependency(line, depe, false); 1327*10d63b7dSRichard Lowe } 1328*10d63b7dSRichard Lowe } 1329*10d63b7dSRichard Lowe 1330*10d63b7dSRichard Lowe /* if matched pattern is a group member, create new target group */ 1331*10d63b7dSRichard Lowe for (group_member = pat_rule->target_group; group_member != NULL; group_member = group_member->next) { 1332*10d63b7dSRichard Lowe Name new_target = group_member->name; 1333*10d63b7dSRichard Lowe if (group_member->name->percent) { 1334*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(string, string_buf); 1335*10d63b7dSRichard Lowe construct_string_from_pattern(group_member->percent_member, percent, &string); 1336*10d63b7dSRichard Lowe new_target = GETNAME(string.buffer.start, FIND_LENGTH); 1337*10d63b7dSRichard Lowe if (new_target == empty_name) { 1338*10d63b7dSRichard Lowe continue; 1339*10d63b7dSRichard Lowe } 1340*10d63b7dSRichard Lowe } 1341*10d63b7dSRichard Lowe 1342*10d63b7dSRichard Lowe /* check for duplicates */ 1343*10d63b7dSRichard Lowe Chain tgm; 1344*10d63b7dSRichard Lowe for (tgm = new_target_group; tgm != NULL; tgm = tgm->next) { 1345*10d63b7dSRichard Lowe if (new_target == tgm->name) { 1346*10d63b7dSRichard Lowe break; 1347*10d63b7dSRichard Lowe } 1348*10d63b7dSRichard Lowe } 1349*10d63b7dSRichard Lowe if (tgm != NULL) { 1350*10d63b7dSRichard Lowe continue; 1351*10d63b7dSRichard Lowe } 1352*10d63b7dSRichard Lowe 1353*10d63b7dSRichard Lowe /* insert it into the targets list */ 1354*10d63b7dSRichard Lowe (*new_target_group_tail) = ALLOC(Chain); 1355*10d63b7dSRichard Lowe (*new_target_group_tail)->name = new_target; 1356*10d63b7dSRichard Lowe (*new_target_group_tail)->next = NULL; 1357*10d63b7dSRichard Lowe new_target_group_tail = &(*new_target_group_tail)->next; 1358*10d63b7dSRichard Lowe } 1359*10d63b7dSRichard Lowe 1360*10d63b7dSRichard Lowe /* now we gathered all dependencies and created target group */ 1361*10d63b7dSRichard Lowe line->body.line.target_group = new_target_group; 1362*10d63b7dSRichard Lowe 1363*10d63b7dSRichard Lowe /* update properties for group members */ 1364*10d63b7dSRichard Lowe for (group_member = new_target_group; group_member != NULL; group_member = group_member->next) { 1365*10d63b7dSRichard Lowe if (group_member->name != target) { 1366*10d63b7dSRichard Lowe group_member->name->prop = target->prop; 1367*10d63b7dSRichard Lowe group_member->name->conditional_cnt = target->conditional_cnt; 1368*10d63b7dSRichard Lowe } 1369*10d63b7dSRichard Lowe } 1370*10d63b7dSRichard Lowe } 1371*10d63b7dSRichard Lowe 1372*10d63b7dSRichard Lowe /* 1373*10d63b7dSRichard Lowe * construct_string_from_pattern 1374*10d63b7dSRichard Lowe * (pat_rule, percent, result) 1375*10d63b7dSRichard Lowe * 1376*10d63b7dSRichard Lowe * after pattern matched a target this routine is called to construct targets and dependencies 1377*10d63b7dSRichard Lowe * strings from this matched pattern rule and a string (percent) with substitutes % sign in pattern. 1378*10d63b7dSRichard Lowe * 1379*10d63b7dSRichard Lowe * Return value: 1380*10d63b7dSRichard Lowe * none 1381*10d63b7dSRichard Lowe * 1382*10d63b7dSRichard Lowe * Parameters: 1383*10d63b7dSRichard Lowe * pat_rule matched pattern rule 1384*10d63b7dSRichard Lowe * percent string containing matched % sign part. 1385*10d63b7dSRichard Lowe * result holds the result of string construction. 1386*10d63b7dSRichard Lowe * 1387*10d63b7dSRichard Lowe */ 1388*10d63b7dSRichard Lowe static void 1389*10d63b7dSRichard Lowe construct_string_from_pattern(Percent pat_rule, String percent, String result) { 1390*10d63b7dSRichard Lowe for (int i = 0; i < pat_rule->patterns_total; i++) { 1391*10d63b7dSRichard Lowe if (pat_rule->patterns[i]->dollar) { 1392*10d63b7dSRichard Lowe expand_value(pat_rule->patterns[i], 1393*10d63b7dSRichard Lowe result, 1394*10d63b7dSRichard Lowe false); 1395*10d63b7dSRichard Lowe 1396*10d63b7dSRichard Lowe } else { 1397*10d63b7dSRichard Lowe append_string(pat_rule->patterns[i]->string_mb, 1398*10d63b7dSRichard Lowe result, 1399*10d63b7dSRichard Lowe pat_rule->patterns[i]->hash.length); 1400*10d63b7dSRichard Lowe } 1401*10d63b7dSRichard Lowe 1402*10d63b7dSRichard Lowe if (i < pat_rule->patterns_total - 1) { 1403*10d63b7dSRichard Lowe append_string(percent->buffer.start, 1404*10d63b7dSRichard Lowe result, 1405*10d63b7dSRichard Lowe percent->text.p - percent->buffer.start); 1406*10d63b7dSRichard Lowe } 1407*10d63b7dSRichard Lowe } 1408*10d63b7dSRichard Lowe 1409*10d63b7dSRichard Lowe if ((result->buffer.start[0] == (int) period_char) && 1410*10d63b7dSRichard Lowe (result->buffer.start[1] == (int) slash_char)) { 1411*10d63b7dSRichard Lowe result->buffer.start += 2; 1412*10d63b7dSRichard Lowe } 1413*10d63b7dSRichard Lowe } 1414*10d63b7dSRichard Lowe 1415*10d63b7dSRichard Lowe /* 1416*10d63b7dSRichard Lowe * dependency_exists(target, line) 1417*10d63b7dSRichard Lowe * 1418*10d63b7dSRichard Lowe * Returns true if the target exists in the 1419*10d63b7dSRichard Lowe * dependency list of the line. 1420*10d63b7dSRichard Lowe * 1421*10d63b7dSRichard Lowe * Return value: 1422*10d63b7dSRichard Lowe * True if target is on dependency list 1423*10d63b7dSRichard Lowe * 1424*10d63b7dSRichard Lowe * Parameters: 1425*10d63b7dSRichard Lowe * target Target we scan for 1426*10d63b7dSRichard Lowe * line We get the dependency list from here 1427*10d63b7dSRichard Lowe * 1428*10d63b7dSRichard Lowe * Global variables used: 1429*10d63b7dSRichard Lowe */ 1430*10d63b7dSRichard Lowe static Boolean 1431*10d63b7dSRichard Lowe dependency_exists(Name target, Property line) 1432*10d63b7dSRichard Lowe { 1433*10d63b7dSRichard Lowe Dependency dp; 1434*10d63b7dSRichard Lowe 1435*10d63b7dSRichard Lowe if (line == NULL) { 1436*10d63b7dSRichard Lowe return false; 1437*10d63b7dSRichard Lowe } 1438*10d63b7dSRichard Lowe for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) { 1439*10d63b7dSRichard Lowe if (dp->name == target) { 1440*10d63b7dSRichard Lowe return true; 1441*10d63b7dSRichard Lowe } 1442*10d63b7dSRichard Lowe } 1443*10d63b7dSRichard Lowe return false; 1444*10d63b7dSRichard Lowe } 1445*10d63b7dSRichard Lowe 1446*10d63b7dSRichard Lowe void 1447*10d63b7dSRichard Lowe add_target_to_chain(Name target, Chain * query) 1448*10d63b7dSRichard Lowe { 1449*10d63b7dSRichard Lowe if (target->is_member && (get_prop(target->prop, member_prop) != NULL)) { 1450*10d63b7dSRichard Lowe target = get_prop(target->prop, member_prop)->body.member.member; 1451*10d63b7dSRichard Lowe } 1452*10d63b7dSRichard Lowe Chain *query_tail; 1453*10d63b7dSRichard Lowe for (query_tail = query; *query_tail != NULL; query_tail = &(*query_tail)->next) { 1454*10d63b7dSRichard Lowe if ((*query_tail)->name == target) { 1455*10d63b7dSRichard Lowe return; 1456*10d63b7dSRichard Lowe } 1457*10d63b7dSRichard Lowe } 1458*10d63b7dSRichard Lowe *query_tail = ALLOC(Chain); 1459*10d63b7dSRichard Lowe (*query_tail)->name = target; 1460*10d63b7dSRichard Lowe (*query_tail)->next = NULL; 1461*10d63b7dSRichard Lowe } 1462*10d63b7dSRichard Lowe 1463