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