Print this page
make: translate using gettext, rather than the unmaintainable catgets


  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      doname.c
  28  *
  29  *      Figure out which targets are out of date and rebuild them
  30  */
  31 
  32 /*
  33  * Included files
  34  */
  35 #include <alloca.h>               /* alloca() */
  36 
  37 
  38 #include <fcntl.h>
  39 #include <mk/defs.h>
  40 #include <mksh/i18n.h>            /* get_char_semantics_value() */
  41 #include <mksh/macro.h>           /* getvar(), expand_value() */
  42 #include <mksh/misc.h>            /* getmem() */
  43 #include <poll.h>
  44 
  45 
  46 #include <signal.h>
  47 
  48 #       include <stropts.h>
  49 
  50 #include <sys/errno.h>
  51 #include <sys/stat.h>
  52 #include <sys/types.h>
  53 #include <sys/utsname.h>  /* uname() */
  54 #include <sys/wait.h>
  55 #include <unistd.h>               /* close() */
  56 
  57 /*
  58  * Defined macros
  59  */
  60 #       define LOCALHOST "localhost"
  61 
  62 #define MAXRULES 100
  63 
  64 // Sleep for .1 seconds between stat()'s
  65 const int       STAT_RETRY_SLEEP_TIME = 100000;
  66 
  67 /*
  68  * typedefs & structs
  69  */


 126  *      Global variables used:
 127  *              build_failed_seen       Set if -k is on and error occurs
 128  *              continue_after_error    Indicates that -k is on
 129  *              report_dependencies     No error msg if -P is on
 130  */
 131 Doname
 132 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
 133 {
 134         int first_time = 1;
 135         (void) fflush(stdout);
 136 try_again:
 137         switch (doname(target, do_get, implicit, automatic)) {
 138         case build_ok:
 139                 second_pass = 0;
 140                 return build_ok;
 141         case build_running:
 142                 second_pass = 0;
 143                 return build_running;
 144         case build_failed:
 145                 if (!continue_after_error) {
 146                         fatal(catgets(catd, 1, 13, "Target `%s' not remade because of errors"),
 147                               target->string_mb);
 148                 }
 149                 build_failed_seen = true;
 150                 second_pass = 0;
 151                 return build_failed;
 152         case build_dont_know:
 153                 /*
 154                  * If we can't figure out how to build an automatic
 155                  * (hidden) dependency, we just ignore it.
 156                  * We later declare the target to be out of date just in
 157                  * case something changed.
 158                  * Also, don't complain if just reporting the dependencies
 159                  * and not building anything.
 160                  */
 161                 if (automatic || (report_dependencies_level > 0)) {
 162                         second_pass = 0;
 163                         return build_dont_know;
 164                 }
 165                 if(first_time) {
 166                         first_time = 0;
 167                         second_pass = 1;
 168                         goto try_again;
 169                 }
 170                 second_pass = 0;
 171                 if (continue_after_error && !svr4) {
 172                         warning(catgets(catd, 1, 14, "Don't know how to make target `%s'"),
 173                                 target->string_mb);
 174                         build_failed_seen = true;
 175                         return build_failed;
 176                 }
 177                 fatal(catgets(catd, 1, 15, "Don't know how to make target `%s'"), target->string_mb);
 178                 break;
 179         }
 180 #ifdef lint
 181         return build_failed;
 182 #endif
 183 }
 184 
 185 
 186 void
 187 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
 188 {
 189         Property line, source_line;
 190         Dependency dependency;
 191 
 192         source_line = get_prop(source->prop, line_prop);
 193         line = maybe_append_prop(target, line_prop);
 194         line->body.line.sccs_command = false;
 195         line->body.line.target = target;
 196         if (line->body.line.command_template == NULL) {
 197                 line->body.line.command_template = source_line->body.line.command_template;


 422                 for (dependency = line->body.line.dependencies;
 423                      dependency != NULL;
 424                      dependency = dependency->next) {
 425                         if (dependency->automatic && !dependency->stale) {
 426                                 auto_count++;
 427                         }
 428                 }
 429                 /* Create vector to hold the current autos */
 430                 automatics =
 431                   (Name *) alloca((int) (auto_count * sizeof (Name)));
 432                 /* Copy them */
 433                 for (p = automatics, dependency = line->body.line.dependencies;
 434                      dependency != NULL;
 435                      dependency = dependency->next) {
 436                         if (dependency->automatic && !dependency->stale) {
 437                                 *p++ = dependency->name;
 438                         }
 439                 }
 440         }
 441         if (debug_level > 1) {
 442                 (void) printf(NOCATGETS("%*sdoname(%s)\n"),
 443                               recursion_level,
 444                               "",
 445                               target->string_mb);
 446         }
 447         recursion_level++;
 448         /* Avoid infinite loops */
 449         if (target->state == build_in_progress) {
 450                 warning(catgets(catd, 1, 16, "Infinite loop: Target `%s' depends on itself"),
 451                         target->string_mb);
 452                 return build_ok;
 453         }
 454         target->state = build_in_progress;
 455 
 456         /* Activate conditional macros for the target */
 457         if (!target->added_pattern_conditionals) {
 458                 add_pattern_conditionals(target);
 459                 target->added_pattern_conditionals = true;
 460         }
 461         if (target->conditional_cnt > 0) {
 462                 old_locals = (Property) alloca(target->conditional_cnt *
 463                                                sizeof (Property_rec));
 464                 set_locals(target, old_locals);
 465         }
 466 
 467 /*
 468  * after making the call to dynamic_dependecies unconditional we can handle
 469  * target names that are same as file name. In this case $$@ in the 
 470  * dependencies did not mean anything. WIth this change it expands it


 668                 /* Use .DEFAULT rule if it is defined. */
 669                 if ((command == NULL) &&
 670                     (result == build_dont_know) &&
 671                     (true_target->colons == no_colon) &&
 672                     default_rule &&
 673                     !implicit) {
 674                         /* Make sure we have a line prop */
 675                         line = maybe_append_prop(target, line_prop);
 676                         command = line;
 677                         Boolean out_of_date;
 678                         if (true_target->is_member) {
 679                                 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
 680                                                                         line->body.line.dependency_time);
 681                         } else {
 682                                 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
 683                                                                     line->body.line.dependency_time);
 684                         }
 685                         if (build_unconditional || out_of_date) {
 686                                 line->body.line.is_out_of_date = true;
 687                                 if (debug_level > 0) {
 688                                         (void) printf(catgets(catd, 1, 17, "%*sBuilding %s using .DEFAULT because it is out of date\n"),
 689                                                       recursion_level,
 690                                                       "",
 691                                                       true_target->string_mb);
 692                                 }
 693                         }
 694                         line->body.line.sccs_command = false;
 695                         line->body.line.command_template = default_rule;
 696                         line->body.line.target = true_target;
 697                         line->body.line.star = NULL;
 698                         line->body.line.less = true_target;
 699                         line->body.line.percent = NULL;
 700                 }
 701         }
 702 
 703         /* We say "target up to date" if no cmd were executed for the target */
 704         if (!target->is_double_colon_parent) {
 705                 commands_done = false;
 706         }
 707 
 708         silent = silent_all;


 862         recursion_level--;
 863         if (target->is_member) {
 864                 Property member;
 865 
 866                 /* Propagate the timestamp from the member file to the member*/
 867                 if ((target->stat.time != file_max_time) &&
 868                     ((member = get_prop(target->prop, member_prop)) != NULL) &&
 869                     (exists(member->body.member.member) > file_doesnt_exist)) {
 870                         target->stat.time =
 871                           member->body.member.member->stat.time;
 872                 }
 873         }
 874         /*
 875          * Check if we found any new auto dependencies when we
 876          * built the target.
 877          */
 878         if ((result == build_ok) && check_auto_dependencies(target,
 879                                                             auto_count,
 880                                                             automatics)) {
 881                 if (debug_level > 0) {
 882                         (void) printf(catgets(catd, 1, 18, "%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
 883                                       recursion_level,
 884                                       "",
 885                                       true_target->string_mb);
 886                 }
 887                 rechecking_target = true;
 888                 saved_commands_done = commands_done;
 889                 goto recheck_target;
 890         }
 891 
 892         if (rechecking_target && !commands_done) {
 893                 commands_done = saved_commands_done;
 894         }
 895 
 896         return result;
 897 }
 898 
 899 /*
 900  * DONE.
 901  *
 902  *      check_dependencies(result, line, do_get,


1015                                 break;
1016                         case build_dont_know:
1017 /*
1018  * If make can't figure out how to make a dependency, maybe the dependency
1019  * is out of date. In this case, we just declare the target out of date
1020  * and go on. If we really need the dependency, the make'ing of the target
1021  * will fail. This will only happen for automatic (hidden) dependencies.
1022  */
1023                                 if(!recheck_conditionals) {
1024                                         line->body.line.is_out_of_date = true;
1025                                 }
1026                                 /*
1027                                  * Make sure the dependency is not saved
1028                                  * in the state file.
1029                                  */
1030                                 dependency->stale = true;
1031                                 rewrite_statefile =
1032                                   command_changed =
1033                                     true;
1034                                 if (debug_level > 0) {
1035                                         (void) printf(catgets(catd, 1, 19, "Target %s rebuilt because dependency %s does not exist\n"),
1036                                                      true_target->string_mb,
1037                                                      dependency->name->string_mb);
1038                                 }
1039                                 break;
1040                         }
1041                         if (dependency->name->depends_on_conditional) {
1042                                 target->depends_on_conditional = true;
1043                         }
1044                         if (dependency->name == force) {
1045                                 target->stat.time =
1046                                   dependency->name->stat.time;
1047                         }
1048                         /*
1049                          * Propagate new timestamp from "member" to
1050                          * "lib.a(member)".
1051                          */
1052                         (void) exists(dependency->name);
1053 
1054                         /* Collect the timestamp of the youngest dependency */
1055                         line->body.line.dependency_time =
1056                           MAX(dependency->name->stat.time,
1057                               line->body.line.dependency_time);
1058 
1059                         /* Correction: do not consider nanosecs for members */
1060                         if(true_target->is_member || dependency->name->is_member) {
1061                                 line->body.line.dependency_time.tv_nsec = 0;
1062                         }
1063 
1064                         if (debug_level > 1) {
1065                                 (void) printf(catgets(catd, 1, 20, "%*sDate(%s)=%s \n"),
1066                                               recursion_level,
1067                                               "",
1068                                               dependency->name->string_mb,
1069                                               time_to_string(dependency->name->
1070                                                              stat.time));
1071                                 if (dependency->name->stat.time > line->body.line.dependency_time) {
1072                                         (void) printf(catgets(catd, 1, 21, "%*sDate-dependencies(%s) set to %s\n"),
1073                                                       recursion_level,
1074                                                       "",
1075                                                       true_target->string_mb,
1076                                                       time_to_string(line->body.line.
1077                                                                      dependency_time));
1078                                 }
1079                         }
1080 
1081                         /* Build the $? list */
1082                         if (true_target->is_member) {
1083                                 if (this_dependency_changed == true) {
1084                                         true_target->stat.time = dependency->name->stat.time;
1085                                         true_target->stat.time.tv_sec--;
1086                                 } else {
1087                                         /* Dina: 
1088                                          * The next statement is commented
1089                                          * out as a fix for bug #1051032.
1090                                          * if dependency hasn't changed
1091                                          * then there's no need to invalidate
1092                                          * true_target. This statemnt causes


1111                         }
1112                         if ((build_unconditional || out_of_date) &&
1113                             (dependency->name != force) &&
1114                             (dependency->stale == false)) {
1115                                 *out_of_date_tail = ALLOC(Chain);
1116                                 if (dependency->name->is_member &&
1117                                     (get_prop(dependency->name->prop,
1118                                               member_prop) != NULL)) {
1119                                         (*out_of_date_tail)->name =
1120                                           get_prop(dependency->name->prop,
1121                                                    member_prop)->
1122                                                      body.member.member;
1123                                 } else {
1124                                         (*out_of_date_tail)->name =
1125                                           dependency->name;
1126                                 }
1127                                 (*out_of_date_tail)->next = NULL;
1128                                 out_of_date_tail = &(*out_of_date_tail)->next;
1129                                 if (debug_level > 0) {
1130                                         if (dependency->name->stat.time == file_max_time) {
1131                                                 (void) printf(catgets(catd, 1, 22, "%*sBuilding %s because %s does not exist\n"),
1132                                                               recursion_level,
1133                                                               "",
1134                                                               true_target->string_mb,
1135                                                               dependency->name->string_mb);
1136                                         } else {
1137                                                 (void) printf(catgets(catd, 1, 23, "%*sBuilding %s because it is out of date relative to %s\n"),
1138                                                               recursion_level,
1139                                                               "",
1140                                                               true_target->string_mb,
1141                                                               dependency->name->string_mb);
1142                                         }
1143                                 }
1144                         }
1145                         if (dependency->name == force) {
1146                                 force->stat.time =
1147                                   file_max_time;
1148                                 force->state = build_dont_know;
1149                         }
1150                 }
1151         }
1152         if (dependencies_running) {
1153                 if (doing_subtree) {
1154                         if (target->conditional_cnt > 0) {
1155                                 reset_locals(target,
1156                                              old_locals,
1157                                              get_prop(target->prop,


1187                         Property        tmp_line;
1188 
1189                         if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1190                                 if(tmp_line->body.line.dependency_time != file_max_time) {
1191                                         target->stat.time =
1192                                           MAX(tmp_line->body.line.dependency_time,
1193                                               target->stat.time);
1194                                 }
1195                         }
1196                 }
1197         }
1198         if ((true_target->is_member) && (dependency_changed == true)) {
1199                 true_target->stat.time = file_no_time;
1200         }
1201         /*
1202          * After scanning all the dependencies, we check the rule
1203          * if we found one.
1204          */
1205         if (line->body.line.command_template != NULL) {
1206                 if (line->body.line.command_template_redefined) {
1207                         warning(catgets(catd, 1, 24, "Too many rules defined for target %s"),
1208                                 target->string_mb);
1209                 }
1210                 *command = line;
1211                 /* Check if the target is out of date */
1212                 Boolean out_of_date;
1213                 if (true_target->is_member) {
1214                         out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1215                                                                 line->body.line.dependency_time);
1216                 } else {
1217                         out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1218                                                             line->body.line.dependency_time);
1219                 }
1220                 if (build_unconditional || out_of_date){
1221                         if(!recheck_conditionals) {
1222                                 line->body.line.is_out_of_date = true;
1223                         }
1224                 }
1225                 line->body.line.sccs_command = false;
1226                 line->body.line.target = true_target;
1227                 if(gnu_style) {


1407                                 /* Create new dependency cell if */
1408                                 /* this is not the first dependency */
1409                                 /* picked from the expansion */
1410                                 if (!reuse_cell) {
1411                                         new_depe = ALLOC(Dependency);
1412                                         new_depe->next = dependency->next;
1413                                         new_depe->automatic = false;
1414                                         new_depe->stale = false;
1415                                         new_depe->built = false;
1416                                         dependency->next = new_depe;
1417                                         dependency = new_depe;
1418                                 }
1419                                 reuse_cell = false;
1420                                 /* Internalize the dependency name */
1421                                 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1422                                 // include "//" and "/./"
1423                                 //dependency->name = GETNAME(start, p - start);
1424                                 dependency->name = normalize_name(start, p - start);
1425                                 if ((debug_level > 0) &&
1426                                     (first_member == NULL)) {
1427                                         (void) printf(catgets(catd, 1, 25, "%*sDynamic dependency `%s' for target `%s'\n"),
1428                                                       recursion_level,
1429                                                       "",
1430                                                       dependency->name->string_mb,
1431                                                       true_target->string_mb);
1432                                 }
1433                                 for (start = p; iswspace(*start); start++);
1434                                 p = start;
1435                         }
1436                 } while ((*p != (int) nul_char) &&
1437                          (*p != (int) parenright_char));
1438                 /* If the expansion was of lib.a(members) format we now */
1439                 /* enter the proper member cells */
1440                 if (first_member != NULL) {
1441                         /* Scan the new dependencies and transform them from */
1442                         /* "foo" to "lib.a(foo)" */
1443                         for (; 1; first_member = first_member->next) {
1444                                 /* Build "lib.a(foo)" name */
1445                                 INIT_STRING_FROM_STACK(string, buffer);
1446                                 APPEND_NAME(lib,
1447                                               &string,
1448                                               (int) lib->hash.length);
1449                                 append_char((int) parenleft_char, &string);
1450                                 APPEND_NAME(first_member->name,
1451                                               &string,
1452                                               FIND_LENGTH);
1453                                 append_char((int) parenright_char, &string);
1454                                 member = first_member->name;
1455                                 /* Replace "foo" with "lib.a(foo)" */
1456                                 first_member->name =
1457                                   GETNAME(string.buffer.start, FIND_LENGTH);
1458                                 if (string.free_after_use) {
1459                                         retmem(string.buffer.start);
1460                                 }
1461                                 if (debug_level > 0) {
1462                                         (void) printf(catgets(catd, 1, 26, "%*sDynamic dependency `%s' for target `%s'\n"),
1463                                                       recursion_level,
1464                                                       "",
1465                                                       first_member->name->
1466                                                       string_mb,
1467                                                       true_target->string_mb);
1468                                 }
1469                                 first_member->name->is_member = lib->is_member;
1470                                 /* Add member property to member */
1471                                 prop = maybe_append_prop(first_member->name,
1472                                                          member_prop);
1473                                 prop->body.member.library = lib;
1474                                 prop->body.member.entry = NULL;
1475                                 prop->body.member.member = member;
1476                                 if (first_member == dependency) {
1477                                         break;
1478                                 }
1479                         }
1480                 }
1481         }
1482         Wstring wcb;


1599         /* If quest, then exit(1) because the target is out of date */
1600         if (quest) {
1601                 if (posix) {
1602                         result = execute_parallel(line, true);
1603                 }
1604                 exit_status = 1;
1605                 exit(1);
1606         }
1607         /* We actually had to do something this time */
1608         rewrite_statefile = commands_done = true;
1609         /*
1610          * If this is an sccs command, we have to do some extra checking
1611          * and possibly complain. If the file can't be gotten because it's
1612          * checked out, we complain and behave as if the command was
1613          * executed eventhough we ignored the command.
1614          */
1615         if (!touch &&
1616             line->body.line.sccs_command &&
1617             (target->stat.time != file_doesnt_exist) &&
1618             ((target->stat.mode & 0222) != 0)) {
1619                 fatal(catgets(catd, 1, 27, "%s is writable so it cannot be sccs gotten"),
1620                       target->string_mb);
1621                 target->has_complained = remember_only = true;
1622         }
1623         /*
1624          * If KEEP_STATE is on, we make sure we have the timestamp for
1625          * .make.state. If .make.state changes during the command run,
1626          * we reread .make.state after the command. We also setup the
1627          * environment variable that asks utilities to report dependencies.
1628          */
1629         if (!touch &&
1630             keep_state &&
1631             !remember_only) {
1632                 (void) exists(make_state);
1633                 if((strlen(temp_file_directory) == 1) && 
1634                         (temp_file_directory[0] == '/')) {
1635                    tmp_file_path[0] = '\0';
1636                 } else {
1637                    strcpy(tmp_file_path, temp_file_directory);
1638                 }
1639                 sprintf(mbs_buffer,
1640                                 NOCATGETS("%s/.make.dependency.%08x.%d.%d"),
1641                                 tmp_file_path,
1642                                 hostid,
1643                                 getpid(),
1644                                 file_number++);
1645                 MBSTOWCS(wcs_buffer, mbs_buffer);
1646                 Boolean fnd;
1647                 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1648                 temp_file_name->stat.is_file = true;
1649                 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1650                 wchar_t *to = string = ALLOC_WC(len);
1651                 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1652                         if (*from == (int) space_char) {
1653                                 *to++ = (int) backslash_char;
1654                         }
1655                         *to++ = *from++;
1656                 }
1657                 *to++ = (int) space_char;
1658                 MBSTOWCS(to, target->string_mb);
1659                 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1660                 (void) SETVAR(sunpro_dependencies,


1810                                 do_assign(rule->command_line, target);
1811                         } else if (report_dependencies_level == 0) {
1812                                 /* Execute command line. */
1813                                 setvar_envvar();
1814                                 result = dosys(rule->command_line,
1815                                                (Boolean) rule->ignore_error,
1816                                                (Boolean) rule->make_refd,
1817                                                /* ds 98.04.23 bug #4085164. make should always show error messages */
1818                                                false,
1819                                                /* BOOLEAN(rule->silent &&
1820                                                        rule->ignore_error), */
1821                                                (Boolean) rule->always_exec,
1822                                                target);
1823                                 check_state(temp_file_name);
1824                         }
1825                 } else {
1826                         result = build_ok;
1827                 }
1828                 if (result == build_failed) {
1829                         if (silent || rule->silent) {
1830                                 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"),
1831                                               rule->command_line->string_mb);
1832                         }
1833                         if (!rule->ignore_error && !ignore_errors) {
1834                                 if (!continue_after_error) {
1835                                         fatal(catgets(catd, 1, 244, "Command failed for target `%s'"),
1836                                               target->string_mb);
1837                                 }
1838                                 /*
1839                                  * Make sure a failing command is not
1840                                  * saved in .make.state.
1841                                  */
1842                                 line->body.line.command_used = NULL;
1843                                 break;
1844                         } else {
1845                                 result = build_ok;
1846                         }
1847                 }
1848         }
1849         for (rule = command; rule != NULL; rule = cmd_tail) {
1850                 cmd_tail = rule->next;
1851                 free(rule);
1852         }
1853         command = NULL;
1854         if (temp_file_name != NULL) {
1855                 free_name(temp_file_name);


2093         while (iswspace(*string)) {
2094                 string++;
2095         }
2096         equal = string;
2097         /* Find "+=" or "=". */
2098         while (!iswspace(*equal) &&
2099                (*equal != (int) plus_char) &&
2100                (*equal != (int) equal_char)) {
2101                 equal++;
2102         }
2103         /* Internalize macro name. */
2104         name = GETNAME(string, equal - string);
2105         /* Skip over "+=" "=". */
2106         while (!((*equal == (int) nul_char) ||
2107                  (*equal == (int) equal_char) ||
2108                  (*equal == (int) plus_char))) {
2109                 equal++;
2110         }
2111         switch (*equal) {
2112         case nul_char:
2113                 fatal(catgets(catd, 1, 31, "= expected in rule `%s' for target `%s'"),
2114                       line->string_mb,
2115                       target->string_mb);
2116         case plus_char:
2117                 append = true;
2118                 equal++;
2119                 break;
2120         }
2121         equal++;
2122         /* Skip over whitespace in front of value. */
2123         while (iswspace(*equal)) {
2124                 equal++;
2125         }
2126         /* Enter new macro value. */
2127         enter_equal(name,
2128                     GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2129                     append);
2130 }
2131 
2132 /*
2133  *      build_command_strings(target, line)


2387                 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2388                 if (!used->ignore_command_dependency) {
2389                         ignore_all_command_dependency = false;
2390                 }
2391                 /* Internalize the expanded and stripped command line */
2392                 new_command_line = GETNAME(start, FIND_LENGTH);
2393                 if ((used->command_line == NULL) &&
2394                     (line->body.line.sccs_command)) {
2395                         used->command_line = new_command_line;
2396                         new_command_longer = false;
2397                 }
2398                 /* Compare it with the old one for command consistency */
2399                 if (used->command_line != new_command_line) {
2400                         Name vpath_translated = vpath_translation(new_command_line);
2401                         if (keep_state &&
2402                             !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2403                                 if (debug_level > 0) {
2404                                         if (used->command_line != NULL
2405                                             && *used->command_line->string_mb !=
2406                                             '\0') {
2407                                                 (void) printf(catgets(catd, 1, 32, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2408                                                               recursion_level,
2409                                                               "",
2410                                                               target->string_mb,
2411                                                               vpath_translated->string_mb,
2412                                                               recursion_level,
2413                                                               "",
2414                                                               used->
2415                                                               command_line->
2416                                                               string_mb);
2417                                         } else {
2418                                                 (void) printf(catgets(catd, 1, 33, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2419                                                               recursion_level,
2420                                                               "",
2421                                                               target->string_mb,
2422                                                               vpath_translated->string_mb,
2423                                                               recursion_level,
2424                                                               "");
2425                                         }
2426                                 }
2427                                 command_changed = true;
2428                                 line->body.line.is_out_of_date = true;
2429                         }
2430                         used->command_line = new_command_line;
2431                 }
2432                 if (command_line.free_after_use) {
2433                         retmem(command_line.buffer.start);
2434                 }
2435         }
2436         /* Check if the old command is longer than the new for */
2437         /* command consistency */
2438         if (used != NULL) {
2439                 *insert = NULL;
2440                 if (keep_state &&
2441                     !ignore_all_command_dependency) {
2442                         if (debug_level > 0) {
2443                                 (void) printf(catgets(catd, 1, 34, "%*sBuilding %s because new command shorter than old\n"),
2444                                               recursion_level,
2445                                               "",
2446                                               target->string_mb);
2447                         }
2448                         command_changed = true;
2449                         line->body.line.is_out_of_date = true;
2450                 }
2451         }
2452         /* Check if the new command is longer than the old command for */
2453         /* command consistency */
2454         if (new_command_longer &&
2455             !ignore_all_command_dependency &&
2456             keep_state) {
2457                 if (debug_level > 0) {
2458                         (void) printf(catgets(catd, 1, 35, "%*sBuilding %s because new command longer than old\n"),
2459                                       recursion_level,
2460                                       "",
2461                                       target->string_mb);
2462                 }
2463                 command_changed = true;
2464                 line->body.line.is_out_of_date = true;
2465         }
2466         /* Unbind the magic macros */
2467         (void) SETVAR(c_at, (Name) NULL, false);
2468         (void) SETVAR(star, (Name) NULL, false);
2469         (void) SETVAR(less_name, (Name) NULL, false);
2470         (void) SETVAR(percent_name, (Name) NULL, false);
2471         (void) SETVAR(query, (Name) NULL, false);
2472         if (query_list != NULL) {
2473                 delete_query_chain(query_list);
2474         }
2475         (void) SETVAR(hat, (Name) NULL, false);
2476         if (hat_list != NULL) {
2477                 delete_query_chain(hat_list);
2478         }


2504  */
2505 static Doname
2506 touch_command(register Property line, register Name target, Doname result)
2507 {
2508         Name                    name;
2509         register Chain          target_group;
2510         String_rec              touch_string;
2511         wchar_t                 buffer[MAXPATHLEN];
2512         Name                    touch_cmd;
2513         Cmd_line                rule;
2514 
2515         for (name = target, target_group = NULL; name != NULL;) {
2516                 if (!name->is_member) {
2517                         /*
2518                          * Build a touch command that can be passed
2519                          * to dosys(). If KEEP_STATE is on, "make -t"
2520                          * will save the proper command, not the
2521                          * "touch" in .make.state.
2522                          */
2523                         INIT_STRING_FROM_STACK(touch_string, buffer);
2524                         MBSTOWCS(wcs_buffer, NOCATGETS("touch "));
2525                         append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2526                         touch_cmd = name;
2527                         if (name->has_vpath_alias_prop) {
2528                                 touch_cmd = get_prop(name->prop,
2529                                                  vpath_alias_prop)->
2530                                                    body.vpath_alias.alias;
2531                         }
2532                         APPEND_NAME(touch_cmd,
2533                                       &touch_string,
2534                                       FIND_LENGTH);
2535                         touch_cmd = GETNAME(touch_string.buffer.start,
2536                                             FIND_LENGTH);
2537                         if (touch_string.free_after_use) {
2538                                 retmem(touch_string.buffer.start);
2539                         }
2540                         if (!silent ||
2541                             do_not_exec_rule &&
2542                             (target_group == NULL)) {
2543                                 (void) printf("%s\n", touch_cmd->string_mb);
2544                         }


2669  *      Global variables used:
2670  *              debug_level     Should we trace activities?
2671  *              recursion_level Used for tracing
2672  *              sccs_get_rule   The rule to used for sccs getting
2673  */
2674 static Doname
2675 sccs_get(register Name target, register Property *command)
2676 {
2677         register int            result;
2678         char                    link[MAXPATHLEN];
2679         String_rec              string;
2680         wchar_t                 name[MAXPATHLEN];
2681         register wchar_t        *p;
2682         timestruc_t             sccs_time;
2683         register Property       line;
2684         int                     sym_link_depth = 0;
2685 
2686         /* For sccs, we need to chase symlinks. */
2687         while (target->stat.is_sym_link) {
2688                 if (sym_link_depth++ > 90) {
2689                         fatal(catgets(catd, 1, 95, "Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2690                               target->string_mb);
2691                 }
2692                 /* Read the value of the link. */
2693                 result = readlink_vroot(target->string_mb,
2694                                         link,
2695                                         sizeof(link),
2696                                         NULL,
2697                                         VROOT_DEFAULT);
2698                 if (result == -1) {
2699                         fatal(catgets(catd, 1, 36, "Can't read symbolic link `%s': %s"),
2700                               target->string_mb, errmsg(errno));
2701                 }
2702                 link[result] = 0;
2703                 /* Use the value to build the proper filename. */
2704                 INIT_STRING_FROM_STACK(string, name);
2705 
2706                 Wstring wcb(target);
2707                 if ((link[0] != slash_char) &&
2708                     ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) {
2709                         append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2710                 }
2711                 append_string(link, &string, result);
2712                 /* Replace the old name with the translated name. */
2713                 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2714                 (void) exists(target);
2715                 if (string.free_after_use) {
2716                         retmem(string.buffer.start);
2717                 }
2718         }
2719 


2751         if ((!target->has_complained &&
2752             (sccs_time != file_doesnt_exist) &&
2753             (sccs_get_rule != NULL))) {
2754                 /* only checking */
2755                 if (command == NULL) {
2756                         return build_ok;
2757                 }
2758                 /*
2759                  * We provide a command line for the target. The line is a
2760                  * "sccs get" command from default.mk.
2761                  */
2762                 line = maybe_append_prop(target, line_prop);
2763                 *command = line;
2764                 if (sccs_time > target->stat.time) {
2765                         /*
2766                          * And only if the plain file is out of date do we
2767                          * request execution of the command.
2768                          */
2769                         line->body.line.is_out_of_date = true;
2770                         if (debug_level > 0) {
2771                                 (void) printf(catgets(catd, 1, 37, "%*sSccs getting %s because s. file is younger than source file\n"),
2772                                               recursion_level,
2773                                               "",
2774                                               target->string_mb);
2775                         }
2776                 }
2777                 line->body.line.sccs_command = true;
2778                 line->body.line.command_template = sccs_get_rule;
2779                 if(!svr4 && (!allrules_read || posix)) {
2780                    if((target->prop) &&
2781                       (target->prop->body.sccs.file) &&
2782                       (target->prop->body.sccs.file->string_mb)) {
2783                       if((strlen(target->prop->body.sccs.file->string_mb) ==
2784                         strlen(target->string_mb) + 2) && 
2785                         (target->prop->body.sccs.file->string_mb[0] == 's') &&
2786                         (target->prop->body.sccs.file->string_mb[1] == '.')) {
2787 
2788                          line->body.line.command_template = get_posix_rule;
2789                       }
2790                    }
2791                 }


2813  *      Global variables used:
2814  *              dot             The Name ".", used as the default dir
2815  */
2816 void
2817 read_directory_of_file(register Name file)
2818 {
2819 
2820         Wstring file_string(file);
2821         wchar_t * wcb = file_string.get_string();
2822         wchar_t usr_include_buf[MAXPATHLEN];
2823         wchar_t usr_include_sys_buf[MAXPATHLEN];
2824 
2825         register Name           directory = dot;
2826         register wchar_t        *p = (wchar_t *) wsrchr(wcb,
2827                                                         (int) slash_char);
2828         register int            length = p - wcb;
2829         static Name             usr_include;
2830         static Name             usr_include_sys;
2831 
2832         if (usr_include == NULL) {
2833                 MBSTOWCS(usr_include_buf, NOCATGETS("/usr/include"));
2834                 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2835                 MBSTOWCS(usr_include_sys_buf, NOCATGETS("/usr/include/sys"));
2836                 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2837         }
2838 
2839         /*
2840          * If the filename contains a "/" we have to extract the path
2841          * Else the path defaults to ".".
2842          */
2843         if (p != NULL) {
2844                 /*
2845                  * Check some popular directories first to possibly
2846                  * save time. Compare string length first to gain speed.
2847                  */
2848                 if ((usr_include->hash.length == length) &&
2849                     IS_WEQUALN(usr_include_buf,
2850                                wcb,
2851                                length)) {
2852                         directory = usr_include;
2853                 } else if ((usr_include_sys->hash.length == length) &&
2854                            IS_WEQUALN(usr_include_sys_buf,
2855                                       wcb,


2948         register Boolean        saved_conditional_macro_used;
2949         Chain                   cond_name;
2950         Chain                   cond_chain;
2951 
2952         if (target->dont_activate_cond_values) {
2953                 return;
2954         }
2955 
2956         saved_conditional_macro_used = conditional_macro_used;
2957 
2958         /* Scan the list of conditional properties and apply each one */
2959         for (conditional = get_prop(target->prop, conditional_prop), i = 0;
2960              conditional != NULL;
2961              conditional = get_prop(conditional->next, conditional_prop),
2962              i++) {
2963                 /* Save the old value */
2964                 old_locals[i].body.macro =
2965                   maybe_append_prop(conditional->body.conditional.name,
2966                                     macro_prop)->body.macro;
2967                 if (debug_level > 1) {
2968                         (void) printf(catgets(catd, 1, 38, "%*sActivating conditional value: "),
2969                                       recursion_level,
2970                                       "");
2971                 }
2972                 /* Set the conditional value. Macros are expanded when the */
2973                 /* macro is refd as usual */
2974                 if ((conditional->body.conditional.name != virtual_root) ||
2975                     (conditional->body.conditional.value != virtual_root)) {
2976                         (void) SETVAR(conditional->body.conditional.name,
2977                                       conditional->body.conditional.value,
2978                                       (Boolean) conditional->body.conditional.append);
2979                 }
2980                 cond_name = ALLOC(Chain);
2981                 cond_name->name = conditional->body.conditional.name;
2982         }
2983         /* Put this target on the front of the chain of conditional targets */
2984         cond_chain = ALLOC(Chain);
2985         cond_chain->name = target;
2986         cond_chain->next = conditional_targets;
2987         conditional_targets = cond_chain;
2988         conditional_macro_used = saved_conditional_macro_used;


3004  */
3005 void
3006 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3007 {
3008         register Property       this_conditional;
3009         Chain                   cond_chain;
3010 
3011         if (target->dont_activate_cond_values) {
3012                 return;
3013         }
3014 
3015         /* Scan the list of conditional properties and restore the old value */
3016         /* to each one Reverse the order relative to when we assigned macros */
3017         this_conditional = get_prop(conditional->next, conditional_prop);
3018         if (this_conditional != NULL) {
3019                 reset_locals(target, old_locals, this_conditional, index+1);
3020         } else {
3021                 /* Remove conditional target from chain */
3022                 if (conditional_targets == NULL ||
3023                     conditional_targets->name != target) {
3024                         warning(catgets(catd, 1, 39, "Internal error: reset target not at head of condtional_targets chain"));
3025                 } else {
3026                         cond_chain = conditional_targets->next;
3027                         retmem_mb((caddr_t) conditional_targets);
3028                         conditional_targets = cond_chain;
3029                 }
3030         }
3031         get_prop(conditional->body.conditional.name->prop,
3032                  macro_prop)->body.macro = old_locals[index].body.macro;
3033         if (conditional->body.conditional.name == virtual_root) {
3034                 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3035         }
3036         if (debug_level > 1) {
3037                 if (old_locals[index].body.macro.value != NULL) {
3038                         (void) printf(catgets(catd, 1, 40, "%*sdeactivating conditional value: %s= %s\n"),
3039                                       recursion_level,
3040                                       "",
3041                                       conditional->body.conditional.name->
3042                                       string_mb,
3043                                       old_locals[index].body.macro.value->
3044                                       string_mb);
3045                 } else {
3046                         (void) printf(catgets(catd, 1, 41, "%*sdeactivating conditional value: %s =\n"),
3047                                       recursion_level,
3048                                       "",
3049                                       conditional->body.conditional.name->
3050                                       string_mb);
3051                 }
3052         }
3053 }
3054 
3055 /*
3056  *      check_auto_dependencies(target, auto_count, automatics)
3057  *
3058  *      Returns true if the target now has a dependency
3059  *      it didn't previously have (saved on automatics).
3060  *
3061  *      Return value:
3062  *                              true if new dependency found
3063  *
3064  *      Parameters:
3065  *              target          Target we check
3066  *              auto_count      Number of old automatic vars




  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      doname.c
  28  *
  29  *      Figure out which targets are out of date and rebuild them
  30  */
  31 
  32 /*
  33  * Included files
  34  */
  35 #include <alloca.h>               /* alloca() */


  36 #include <fcntl.h>
  37 #include <mk/defs.h>
  38 #include <mksh/i18n.h>            /* get_char_semantics_value() */
  39 #include <mksh/macro.h>           /* getvar(), expand_value() */
  40 #include <mksh/misc.h>            /* getmem() */
  41 #include <poll.h>
  42 #include <libintl.h>

  43 #include <signal.h>
  44 #include <stropts.h>


  45 #include <sys/errno.h>
  46 #include <sys/stat.h>
  47 #include <sys/types.h>
  48 #include <sys/utsname.h>  /* uname() */
  49 #include <sys/wait.h>
  50 #include <unistd.h>               /* close() */
  51 
  52 /*
  53  * Defined macros
  54  */
  55 #       define LOCALHOST "localhost"
  56 
  57 #define MAXRULES 100
  58 
  59 // Sleep for .1 seconds between stat()'s
  60 const int       STAT_RETRY_SLEEP_TIME = 100000;
  61 
  62 /*
  63  * typedefs & structs
  64  */


 121  *      Global variables used:
 122  *              build_failed_seen       Set if -k is on and error occurs
 123  *              continue_after_error    Indicates that -k is on
 124  *              report_dependencies     No error msg if -P is on
 125  */
 126 Doname
 127 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
 128 {
 129         int first_time = 1;
 130         (void) fflush(stdout);
 131 try_again:
 132         switch (doname(target, do_get, implicit, automatic)) {
 133         case build_ok:
 134                 second_pass = 0;
 135                 return build_ok;
 136         case build_running:
 137                 second_pass = 0;
 138                 return build_running;
 139         case build_failed:
 140                 if (!continue_after_error) {
 141                         fatal(gettext("Target `%s' not remade because of errors"),
 142                               target->string_mb);
 143                 }
 144                 build_failed_seen = true;
 145                 second_pass = 0;
 146                 return build_failed;
 147         case build_dont_know:
 148                 /*
 149                  * If we can't figure out how to build an automatic
 150                  * (hidden) dependency, we just ignore it.
 151                  * We later declare the target to be out of date just in
 152                  * case something changed.
 153                  * Also, don't complain if just reporting the dependencies
 154                  * and not building anything.
 155                  */
 156                 if (automatic || (report_dependencies_level > 0)) {
 157                         second_pass = 0;
 158                         return build_dont_know;
 159                 }
 160                 if(first_time) {
 161                         first_time = 0;
 162                         second_pass = 1;
 163                         goto try_again;
 164                 }
 165                 second_pass = 0;
 166                 if (continue_after_error && !svr4) {
 167                         warning(gettext("Don't know how to make target `%s'"),
 168                                 target->string_mb);
 169                         build_failed_seen = true;
 170                         return build_failed;
 171                 }
 172                 fatal(gettext("Don't know how to make target `%s'"), target->string_mb);
 173                 break;
 174         }
 175 #ifdef lint
 176         return build_failed;
 177 #endif
 178 }
 179 
 180 
 181 void
 182 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
 183 {
 184         Property line, source_line;
 185         Dependency dependency;
 186 
 187         source_line = get_prop(source->prop, line_prop);
 188         line = maybe_append_prop(target, line_prop);
 189         line->body.line.sccs_command = false;
 190         line->body.line.target = target;
 191         if (line->body.line.command_template == NULL) {
 192                 line->body.line.command_template = source_line->body.line.command_template;


 417                 for (dependency = line->body.line.dependencies;
 418                      dependency != NULL;
 419                      dependency = dependency->next) {
 420                         if (dependency->automatic && !dependency->stale) {
 421                                 auto_count++;
 422                         }
 423                 }
 424                 /* Create vector to hold the current autos */
 425                 automatics =
 426                   (Name *) alloca((int) (auto_count * sizeof (Name)));
 427                 /* Copy them */
 428                 for (p = automatics, dependency = line->body.line.dependencies;
 429                      dependency != NULL;
 430                      dependency = dependency->next) {
 431                         if (dependency->automatic && !dependency->stale) {
 432                                 *p++ = dependency->name;
 433                         }
 434                 }
 435         }
 436         if (debug_level > 1) {
 437                 (void) printf("%*sdoname(%s)\n",
 438                               recursion_level,
 439                               "",
 440                               target->string_mb);
 441         }
 442         recursion_level++;
 443         /* Avoid infinite loops */
 444         if (target->state == build_in_progress) {
 445                 warning(gettext("Infinite loop: Target `%s' depends on itself"),
 446                         target->string_mb);
 447                 return build_ok;
 448         }
 449         target->state = build_in_progress;
 450 
 451         /* Activate conditional macros for the target */
 452         if (!target->added_pattern_conditionals) {
 453                 add_pattern_conditionals(target);
 454                 target->added_pattern_conditionals = true;
 455         }
 456         if (target->conditional_cnt > 0) {
 457                 old_locals = (Property) alloca(target->conditional_cnt *
 458                                                sizeof (Property_rec));
 459                 set_locals(target, old_locals);
 460         }
 461 
 462 /*
 463  * after making the call to dynamic_dependecies unconditional we can handle
 464  * target names that are same as file name. In this case $$@ in the 
 465  * dependencies did not mean anything. WIth this change it expands it


 663                 /* Use .DEFAULT rule if it is defined. */
 664                 if ((command == NULL) &&
 665                     (result == build_dont_know) &&
 666                     (true_target->colons == no_colon) &&
 667                     default_rule &&
 668                     !implicit) {
 669                         /* Make sure we have a line prop */
 670                         line = maybe_append_prop(target, line_prop);
 671                         command = line;
 672                         Boolean out_of_date;
 673                         if (true_target->is_member) {
 674                                 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
 675                                                                         line->body.line.dependency_time);
 676                         } else {
 677                                 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
 678                                                                     line->body.line.dependency_time);
 679                         }
 680                         if (build_unconditional || out_of_date) {
 681                                 line->body.line.is_out_of_date = true;
 682                                 if (debug_level > 0) {
 683                                         (void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
 684                                                       recursion_level,
 685                                                       "",
 686                                                       true_target->string_mb);
 687                                 }
 688                         }
 689                         line->body.line.sccs_command = false;
 690                         line->body.line.command_template = default_rule;
 691                         line->body.line.target = true_target;
 692                         line->body.line.star = NULL;
 693                         line->body.line.less = true_target;
 694                         line->body.line.percent = NULL;
 695                 }
 696         }
 697 
 698         /* We say "target up to date" if no cmd were executed for the target */
 699         if (!target->is_double_colon_parent) {
 700                 commands_done = false;
 701         }
 702 
 703         silent = silent_all;


 857         recursion_level--;
 858         if (target->is_member) {
 859                 Property member;
 860 
 861                 /* Propagate the timestamp from the member file to the member*/
 862                 if ((target->stat.time != file_max_time) &&
 863                     ((member = get_prop(target->prop, member_prop)) != NULL) &&
 864                     (exists(member->body.member.member) > file_doesnt_exist)) {
 865                         target->stat.time =
 866                           member->body.member.member->stat.time;
 867                 }
 868         }
 869         /*
 870          * Check if we found any new auto dependencies when we
 871          * built the target.
 872          */
 873         if ((result == build_ok) && check_auto_dependencies(target,
 874                                                             auto_count,
 875                                                             automatics)) {
 876                 if (debug_level > 0) {
 877                         (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
 878                                       recursion_level,
 879                                       "",
 880                                       true_target->string_mb);
 881                 }
 882                 rechecking_target = true;
 883                 saved_commands_done = commands_done;
 884                 goto recheck_target;
 885         }
 886 
 887         if (rechecking_target && !commands_done) {
 888                 commands_done = saved_commands_done;
 889         }
 890 
 891         return result;
 892 }
 893 
 894 /*
 895  * DONE.
 896  *
 897  *      check_dependencies(result, line, do_get,


1010                                 break;
1011                         case build_dont_know:
1012 /*
1013  * If make can't figure out how to make a dependency, maybe the dependency
1014  * is out of date. In this case, we just declare the target out of date
1015  * and go on. If we really need the dependency, the make'ing of the target
1016  * will fail. This will only happen for automatic (hidden) dependencies.
1017  */
1018                                 if(!recheck_conditionals) {
1019                                         line->body.line.is_out_of_date = true;
1020                                 }
1021                                 /*
1022                                  * Make sure the dependency is not saved
1023                                  * in the state file.
1024                                  */
1025                                 dependency->stale = true;
1026                                 rewrite_statefile =
1027                                   command_changed =
1028                                     true;
1029                                 if (debug_level > 0) {
1030                                         (void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
1031                                                      true_target->string_mb,
1032                                                      dependency->name->string_mb);
1033                                 }
1034                                 break;
1035                         }
1036                         if (dependency->name->depends_on_conditional) {
1037                                 target->depends_on_conditional = true;
1038                         }
1039                         if (dependency->name == force) {
1040                                 target->stat.time =
1041                                   dependency->name->stat.time;
1042                         }
1043                         /*
1044                          * Propagate new timestamp from "member" to
1045                          * "lib.a(member)".
1046                          */
1047                         (void) exists(dependency->name);
1048 
1049                         /* Collect the timestamp of the youngest dependency */
1050                         line->body.line.dependency_time =
1051                           MAX(dependency->name->stat.time,
1052                               line->body.line.dependency_time);
1053 
1054                         /* Correction: do not consider nanosecs for members */
1055                         if(true_target->is_member || dependency->name->is_member) {
1056                                 line->body.line.dependency_time.tv_nsec = 0;
1057                         }
1058 
1059                         if (debug_level > 1) {
1060                                 (void) printf(gettext("%*sDate(%s)=%s \n"),
1061                                               recursion_level,
1062                                               "",
1063                                               dependency->name->string_mb,
1064                                               time_to_string(dependency->name->
1065                                                              stat.time));
1066                                 if (dependency->name->stat.time > line->body.line.dependency_time) {
1067                                         (void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
1068                                                       recursion_level,
1069                                                       "",
1070                                                       true_target->string_mb,
1071                                                       time_to_string(line->body.line.
1072                                                                      dependency_time));
1073                                 }
1074                         }
1075 
1076                         /* Build the $? list */
1077                         if (true_target->is_member) {
1078                                 if (this_dependency_changed == true) {
1079                                         true_target->stat.time = dependency->name->stat.time;
1080                                         true_target->stat.time.tv_sec--;
1081                                 } else {
1082                                         /* Dina: 
1083                                          * The next statement is commented
1084                                          * out as a fix for bug #1051032.
1085                                          * if dependency hasn't changed
1086                                          * then there's no need to invalidate
1087                                          * true_target. This statemnt causes


1106                         }
1107                         if ((build_unconditional || out_of_date) &&
1108                             (dependency->name != force) &&
1109                             (dependency->stale == false)) {
1110                                 *out_of_date_tail = ALLOC(Chain);
1111                                 if (dependency->name->is_member &&
1112                                     (get_prop(dependency->name->prop,
1113                                               member_prop) != NULL)) {
1114                                         (*out_of_date_tail)->name =
1115                                           get_prop(dependency->name->prop,
1116                                                    member_prop)->
1117                                                      body.member.member;
1118                                 } else {
1119                                         (*out_of_date_tail)->name =
1120                                           dependency->name;
1121                                 }
1122                                 (*out_of_date_tail)->next = NULL;
1123                                 out_of_date_tail = &(*out_of_date_tail)->next;
1124                                 if (debug_level > 0) {
1125                                         if (dependency->name->stat.time == file_max_time) {
1126                                                 (void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
1127                                                               recursion_level,
1128                                                               "",
1129                                                               true_target->string_mb,
1130                                                               dependency->name->string_mb);
1131                                         } else {
1132                                                 (void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
1133                                                               recursion_level,
1134                                                               "",
1135                                                               true_target->string_mb,
1136                                                               dependency->name->string_mb);
1137                                         }
1138                                 }
1139                         }
1140                         if (dependency->name == force) {
1141                                 force->stat.time =
1142                                   file_max_time;
1143                                 force->state = build_dont_know;
1144                         }
1145                 }
1146         }
1147         if (dependencies_running) {
1148                 if (doing_subtree) {
1149                         if (target->conditional_cnt > 0) {
1150                                 reset_locals(target,
1151                                              old_locals,
1152                                              get_prop(target->prop,


1182                         Property        tmp_line;
1183 
1184                         if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1185                                 if(tmp_line->body.line.dependency_time != file_max_time) {
1186                                         target->stat.time =
1187                                           MAX(tmp_line->body.line.dependency_time,
1188                                               target->stat.time);
1189                                 }
1190                         }
1191                 }
1192         }
1193         if ((true_target->is_member) && (dependency_changed == true)) {
1194                 true_target->stat.time = file_no_time;
1195         }
1196         /*
1197          * After scanning all the dependencies, we check the rule
1198          * if we found one.
1199          */
1200         if (line->body.line.command_template != NULL) {
1201                 if (line->body.line.command_template_redefined) {
1202                         warning(gettext("Too many rules defined for target %s"),
1203                                 target->string_mb);
1204                 }
1205                 *command = line;
1206                 /* Check if the target is out of date */
1207                 Boolean out_of_date;
1208                 if (true_target->is_member) {
1209                         out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1210                                                                 line->body.line.dependency_time);
1211                 } else {
1212                         out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1213                                                             line->body.line.dependency_time);
1214                 }
1215                 if (build_unconditional || out_of_date){
1216                         if(!recheck_conditionals) {
1217                                 line->body.line.is_out_of_date = true;
1218                         }
1219                 }
1220                 line->body.line.sccs_command = false;
1221                 line->body.line.target = true_target;
1222                 if(gnu_style) {


1402                                 /* Create new dependency cell if */
1403                                 /* this is not the first dependency */
1404                                 /* picked from the expansion */
1405                                 if (!reuse_cell) {
1406                                         new_depe = ALLOC(Dependency);
1407                                         new_depe->next = dependency->next;
1408                                         new_depe->automatic = false;
1409                                         new_depe->stale = false;
1410                                         new_depe->built = false;
1411                                         dependency->next = new_depe;
1412                                         dependency = new_depe;
1413                                 }
1414                                 reuse_cell = false;
1415                                 /* Internalize the dependency name */
1416                                 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1417                                 // include "//" and "/./"
1418                                 //dependency->name = GETNAME(start, p - start);
1419                                 dependency->name = normalize_name(start, p - start);
1420                                 if ((debug_level > 0) &&
1421                                     (first_member == NULL)) {
1422                                         (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1423                                                       recursion_level,
1424                                                       "",
1425                                                       dependency->name->string_mb,
1426                                                       true_target->string_mb);
1427                                 }
1428                                 for (start = p; iswspace(*start); start++);
1429                                 p = start;
1430                         }
1431                 } while ((*p != (int) nul_char) &&
1432                          (*p != (int) parenright_char));
1433                 /* If the expansion was of lib.a(members) format we now */
1434                 /* enter the proper member cells */
1435                 if (first_member != NULL) {
1436                         /* Scan the new dependencies and transform them from */
1437                         /* "foo" to "lib.a(foo)" */
1438                         for (; 1; first_member = first_member->next) {
1439                                 /* Build "lib.a(foo)" name */
1440                                 INIT_STRING_FROM_STACK(string, buffer);
1441                                 APPEND_NAME(lib,
1442                                               &string,
1443                                               (int) lib->hash.length);
1444                                 append_char((int) parenleft_char, &string);
1445                                 APPEND_NAME(first_member->name,
1446                                               &string,
1447                                               FIND_LENGTH);
1448                                 append_char((int) parenright_char, &string);
1449                                 member = first_member->name;
1450                                 /* Replace "foo" with "lib.a(foo)" */
1451                                 first_member->name =
1452                                   GETNAME(string.buffer.start, FIND_LENGTH);
1453                                 if (string.free_after_use) {
1454                                         retmem(string.buffer.start);
1455                                 }
1456                                 if (debug_level > 0) {
1457                                         (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1458                                                       recursion_level,
1459                                                       "",
1460                                                       first_member->name->
1461                                                       string_mb,
1462                                                       true_target->string_mb);
1463                                 }
1464                                 first_member->name->is_member = lib->is_member;
1465                                 /* Add member property to member */
1466                                 prop = maybe_append_prop(first_member->name,
1467                                                          member_prop);
1468                                 prop->body.member.library = lib;
1469                                 prop->body.member.entry = NULL;
1470                                 prop->body.member.member = member;
1471                                 if (first_member == dependency) {
1472                                         break;
1473                                 }
1474                         }
1475                 }
1476         }
1477         Wstring wcb;


1594         /* If quest, then exit(1) because the target is out of date */
1595         if (quest) {
1596                 if (posix) {
1597                         result = execute_parallel(line, true);
1598                 }
1599                 exit_status = 1;
1600                 exit(1);
1601         }
1602         /* We actually had to do something this time */
1603         rewrite_statefile = commands_done = true;
1604         /*
1605          * If this is an sccs command, we have to do some extra checking
1606          * and possibly complain. If the file can't be gotten because it's
1607          * checked out, we complain and behave as if the command was
1608          * executed eventhough we ignored the command.
1609          */
1610         if (!touch &&
1611             line->body.line.sccs_command &&
1612             (target->stat.time != file_doesnt_exist) &&
1613             ((target->stat.mode & 0222) != 0)) {
1614                 fatal(gettext("%s is writable so it cannot be sccs gotten"),
1615                       target->string_mb);
1616                 target->has_complained = remember_only = true;
1617         }
1618         /*
1619          * If KEEP_STATE is on, we make sure we have the timestamp for
1620          * .make.state. If .make.state changes during the command run,
1621          * we reread .make.state after the command. We also setup the
1622          * environment variable that asks utilities to report dependencies.
1623          */
1624         if (!touch &&
1625             keep_state &&
1626             !remember_only) {
1627                 (void) exists(make_state);
1628                 if((strlen(temp_file_directory) == 1) && 
1629                         (temp_file_directory[0] == '/')) {
1630                    tmp_file_path[0] = '\0';
1631                 } else {
1632                    strcpy(tmp_file_path, temp_file_directory);
1633                 }
1634                 sprintf(mbs_buffer,
1635                                 "%s/.make.dependency.%08x.%d.%d",
1636                                 tmp_file_path,
1637                                 hostid,
1638                                 getpid(),
1639                                 file_number++);
1640                 MBSTOWCS(wcs_buffer, mbs_buffer);
1641                 Boolean fnd;
1642                 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1643                 temp_file_name->stat.is_file = true;
1644                 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1645                 wchar_t *to = string = ALLOC_WC(len);
1646                 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1647                         if (*from == (int) space_char) {
1648                                 *to++ = (int) backslash_char;
1649                         }
1650                         *to++ = *from++;
1651                 }
1652                 *to++ = (int) space_char;
1653                 MBSTOWCS(to, target->string_mb);
1654                 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1655                 (void) SETVAR(sunpro_dependencies,


1805                                 do_assign(rule->command_line, target);
1806                         } else if (report_dependencies_level == 0) {
1807                                 /* Execute command line. */
1808                                 setvar_envvar();
1809                                 result = dosys(rule->command_line,
1810                                                (Boolean) rule->ignore_error,
1811                                                (Boolean) rule->make_refd,
1812                                                /* ds 98.04.23 bug #4085164. make should always show error messages */
1813                                                false,
1814                                                /* BOOLEAN(rule->silent &&
1815                                                        rule->ignore_error), */
1816                                                (Boolean) rule->always_exec,
1817                                                target);
1818                                 check_state(temp_file_name);
1819                         }
1820                 } else {
1821                         result = build_ok;
1822                 }
1823                 if (result == build_failed) {
1824                         if (silent || rule->silent) {
1825                                 (void) printf(gettext("The following command caused the error:\n%s\n"),
1826                                               rule->command_line->string_mb);
1827                         }
1828                         if (!rule->ignore_error && !ignore_errors) {
1829                                 if (!continue_after_error) {
1830                                         fatal(gettext("Command failed for target `%s'"),
1831                                               target->string_mb);
1832                                 }
1833                                 /*
1834                                  * Make sure a failing command is not
1835                                  * saved in .make.state.
1836                                  */
1837                                 line->body.line.command_used = NULL;
1838                                 break;
1839                         } else {
1840                                 result = build_ok;
1841                         }
1842                 }
1843         }
1844         for (rule = command; rule != NULL; rule = cmd_tail) {
1845                 cmd_tail = rule->next;
1846                 free(rule);
1847         }
1848         command = NULL;
1849         if (temp_file_name != NULL) {
1850                 free_name(temp_file_name);


2088         while (iswspace(*string)) {
2089                 string++;
2090         }
2091         equal = string;
2092         /* Find "+=" or "=". */
2093         while (!iswspace(*equal) &&
2094                (*equal != (int) plus_char) &&
2095                (*equal != (int) equal_char)) {
2096                 equal++;
2097         }
2098         /* Internalize macro name. */
2099         name = GETNAME(string, equal - string);
2100         /* Skip over "+=" "=". */
2101         while (!((*equal == (int) nul_char) ||
2102                  (*equal == (int) equal_char) ||
2103                  (*equal == (int) plus_char))) {
2104                 equal++;
2105         }
2106         switch (*equal) {
2107         case nul_char:
2108                 fatal(gettext("= expected in rule `%s' for target `%s'"),
2109                       line->string_mb,
2110                       target->string_mb);
2111         case plus_char:
2112                 append = true;
2113                 equal++;
2114                 break;
2115         }
2116         equal++;
2117         /* Skip over whitespace in front of value. */
2118         while (iswspace(*equal)) {
2119                 equal++;
2120         }
2121         /* Enter new macro value. */
2122         enter_equal(name,
2123                     GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2124                     append);
2125 }
2126 
2127 /*
2128  *      build_command_strings(target, line)


2382                 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2383                 if (!used->ignore_command_dependency) {
2384                         ignore_all_command_dependency = false;
2385                 }
2386                 /* Internalize the expanded and stripped command line */
2387                 new_command_line = GETNAME(start, FIND_LENGTH);
2388                 if ((used->command_line == NULL) &&
2389                     (line->body.line.sccs_command)) {
2390                         used->command_line = new_command_line;
2391                         new_command_longer = false;
2392                 }
2393                 /* Compare it with the old one for command consistency */
2394                 if (used->command_line != new_command_line) {
2395                         Name vpath_translated = vpath_translation(new_command_line);
2396                         if (keep_state &&
2397                             !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2398                                 if (debug_level > 0) {
2399                                         if (used->command_line != NULL
2400                                             && *used->command_line->string_mb !=
2401                                             '\0') {
2402                                                 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2403                                                               recursion_level,
2404                                                               "",
2405                                                               target->string_mb,
2406                                                               vpath_translated->string_mb,
2407                                                               recursion_level,
2408                                                               "",
2409                                                               used->
2410                                                               command_line->
2411                                                               string_mb);
2412                                         } else {
2413                                                 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2414                                                               recursion_level,
2415                                                               "",
2416                                                               target->string_mb,
2417                                                               vpath_translated->string_mb,
2418                                                               recursion_level,
2419                                                               "");
2420                                         }
2421                                 }
2422                                 command_changed = true;
2423                                 line->body.line.is_out_of_date = true;
2424                         }
2425                         used->command_line = new_command_line;
2426                 }
2427                 if (command_line.free_after_use) {
2428                         retmem(command_line.buffer.start);
2429                 }
2430         }
2431         /* Check if the old command is longer than the new for */
2432         /* command consistency */
2433         if (used != NULL) {
2434                 *insert = NULL;
2435                 if (keep_state &&
2436                     !ignore_all_command_dependency) {
2437                         if (debug_level > 0) {
2438                                 (void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
2439                                               recursion_level,
2440                                               "",
2441                                               target->string_mb);
2442                         }
2443                         command_changed = true;
2444                         line->body.line.is_out_of_date = true;
2445                 }
2446         }
2447         /* Check if the new command is longer than the old command for */
2448         /* command consistency */
2449         if (new_command_longer &&
2450             !ignore_all_command_dependency &&
2451             keep_state) {
2452                 if (debug_level > 0) {
2453                         (void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
2454                                       recursion_level,
2455                                       "",
2456                                       target->string_mb);
2457                 }
2458                 command_changed = true;
2459                 line->body.line.is_out_of_date = true;
2460         }
2461         /* Unbind the magic macros */
2462         (void) SETVAR(c_at, (Name) NULL, false);
2463         (void) SETVAR(star, (Name) NULL, false);
2464         (void) SETVAR(less_name, (Name) NULL, false);
2465         (void) SETVAR(percent_name, (Name) NULL, false);
2466         (void) SETVAR(query, (Name) NULL, false);
2467         if (query_list != NULL) {
2468                 delete_query_chain(query_list);
2469         }
2470         (void) SETVAR(hat, (Name) NULL, false);
2471         if (hat_list != NULL) {
2472                 delete_query_chain(hat_list);
2473         }


2499  */
2500 static Doname
2501 touch_command(register Property line, register Name target, Doname result)
2502 {
2503         Name                    name;
2504         register Chain          target_group;
2505         String_rec              touch_string;
2506         wchar_t                 buffer[MAXPATHLEN];
2507         Name                    touch_cmd;
2508         Cmd_line                rule;
2509 
2510         for (name = target, target_group = NULL; name != NULL;) {
2511                 if (!name->is_member) {
2512                         /*
2513                          * Build a touch command that can be passed
2514                          * to dosys(). If KEEP_STATE is on, "make -t"
2515                          * will save the proper command, not the
2516                          * "touch" in .make.state.
2517                          */
2518                         INIT_STRING_FROM_STACK(touch_string, buffer);
2519                         MBSTOWCS(wcs_buffer, "touch ");
2520                         append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2521                         touch_cmd = name;
2522                         if (name->has_vpath_alias_prop) {
2523                                 touch_cmd = get_prop(name->prop,
2524                                                  vpath_alias_prop)->
2525                                                    body.vpath_alias.alias;
2526                         }
2527                         APPEND_NAME(touch_cmd,
2528                                       &touch_string,
2529                                       FIND_LENGTH);
2530                         touch_cmd = GETNAME(touch_string.buffer.start,
2531                                             FIND_LENGTH);
2532                         if (touch_string.free_after_use) {
2533                                 retmem(touch_string.buffer.start);
2534                         }
2535                         if (!silent ||
2536                             do_not_exec_rule &&
2537                             (target_group == NULL)) {
2538                                 (void) printf("%s\n", touch_cmd->string_mb);
2539                         }


2664  *      Global variables used:
2665  *              debug_level     Should we trace activities?
2666  *              recursion_level Used for tracing
2667  *              sccs_get_rule   The rule to used for sccs getting
2668  */
2669 static Doname
2670 sccs_get(register Name target, register Property *command)
2671 {
2672         register int            result;
2673         char                    link[MAXPATHLEN];
2674         String_rec              string;
2675         wchar_t                 name[MAXPATHLEN];
2676         register wchar_t        *p;
2677         timestruc_t             sccs_time;
2678         register Property       line;
2679         int                     sym_link_depth = 0;
2680 
2681         /* For sccs, we need to chase symlinks. */
2682         while (target->stat.is_sym_link) {
2683                 if (sym_link_depth++ > 90) {
2684                         fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2685                               target->string_mb);
2686                 }
2687                 /* Read the value of the link. */
2688                 result = readlink_vroot(target->string_mb,
2689                                         link,
2690                                         sizeof(link),
2691                                         NULL,
2692                                         VROOT_DEFAULT);
2693                 if (result == -1) {
2694                         fatal(gettext("Can't read symbolic link `%s': %s"),
2695                               target->string_mb, errmsg(errno));
2696                 }
2697                 link[result] = 0;
2698                 /* Use the value to build the proper filename. */
2699                 INIT_STRING_FROM_STACK(string, name);
2700 
2701                 Wstring wcb(target);
2702                 if ((link[0] != slash_char) &&
2703                     ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) {
2704                         append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2705                 }
2706                 append_string(link, &string, result);
2707                 /* Replace the old name with the translated name. */
2708                 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2709                 (void) exists(target);
2710                 if (string.free_after_use) {
2711                         retmem(string.buffer.start);
2712                 }
2713         }
2714 


2746         if ((!target->has_complained &&
2747             (sccs_time != file_doesnt_exist) &&
2748             (sccs_get_rule != NULL))) {
2749                 /* only checking */
2750                 if (command == NULL) {
2751                         return build_ok;
2752                 }
2753                 /*
2754                  * We provide a command line for the target. The line is a
2755                  * "sccs get" command from default.mk.
2756                  */
2757                 line = maybe_append_prop(target, line_prop);
2758                 *command = line;
2759                 if (sccs_time > target->stat.time) {
2760                         /*
2761                          * And only if the plain file is out of date do we
2762                          * request execution of the command.
2763                          */
2764                         line->body.line.is_out_of_date = true;
2765                         if (debug_level > 0) {
2766                                 (void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
2767                                               recursion_level,
2768                                               "",
2769                                               target->string_mb);
2770                         }
2771                 }
2772                 line->body.line.sccs_command = true;
2773                 line->body.line.command_template = sccs_get_rule;
2774                 if(!svr4 && (!allrules_read || posix)) {
2775                    if((target->prop) &&
2776                       (target->prop->body.sccs.file) &&
2777                       (target->prop->body.sccs.file->string_mb)) {
2778                       if((strlen(target->prop->body.sccs.file->string_mb) ==
2779                         strlen(target->string_mb) + 2) && 
2780                         (target->prop->body.sccs.file->string_mb[0] == 's') &&
2781                         (target->prop->body.sccs.file->string_mb[1] == '.')) {
2782 
2783                          line->body.line.command_template = get_posix_rule;
2784                       }
2785                    }
2786                 }


2808  *      Global variables used:
2809  *              dot             The Name ".", used as the default dir
2810  */
2811 void
2812 read_directory_of_file(register Name file)
2813 {
2814 
2815         Wstring file_string(file);
2816         wchar_t * wcb = file_string.get_string();
2817         wchar_t usr_include_buf[MAXPATHLEN];
2818         wchar_t usr_include_sys_buf[MAXPATHLEN];
2819 
2820         register Name           directory = dot;
2821         register wchar_t        *p = (wchar_t *) wsrchr(wcb,
2822                                                         (int) slash_char);
2823         register int            length = p - wcb;
2824         static Name             usr_include;
2825         static Name             usr_include_sys;
2826 
2827         if (usr_include == NULL) {
2828                 MBSTOWCS(usr_include_buf, "/usr/include");
2829                 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2830                 MBSTOWCS(usr_include_sys_buf, "/usr/include/sys");
2831                 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2832         }
2833 
2834         /*
2835          * If the filename contains a "/" we have to extract the path
2836          * Else the path defaults to ".".
2837          */
2838         if (p != NULL) {
2839                 /*
2840                  * Check some popular directories first to possibly
2841                  * save time. Compare string length first to gain speed.
2842                  */
2843                 if ((usr_include->hash.length == length) &&
2844                     IS_WEQUALN(usr_include_buf,
2845                                wcb,
2846                                length)) {
2847                         directory = usr_include;
2848                 } else if ((usr_include_sys->hash.length == length) &&
2849                            IS_WEQUALN(usr_include_sys_buf,
2850                                       wcb,


2943         register Boolean        saved_conditional_macro_used;
2944         Chain                   cond_name;
2945         Chain                   cond_chain;
2946 
2947         if (target->dont_activate_cond_values) {
2948                 return;
2949         }
2950 
2951         saved_conditional_macro_used = conditional_macro_used;
2952 
2953         /* Scan the list of conditional properties and apply each one */
2954         for (conditional = get_prop(target->prop, conditional_prop), i = 0;
2955              conditional != NULL;
2956              conditional = get_prop(conditional->next, conditional_prop),
2957              i++) {
2958                 /* Save the old value */
2959                 old_locals[i].body.macro =
2960                   maybe_append_prop(conditional->body.conditional.name,
2961                                     macro_prop)->body.macro;
2962                 if (debug_level > 1) {
2963                         (void) printf(gettext("%*sActivating conditional value: "),
2964                                       recursion_level,
2965                                       "");
2966                 }
2967                 /* Set the conditional value. Macros are expanded when the */
2968                 /* macro is refd as usual */
2969                 if ((conditional->body.conditional.name != virtual_root) ||
2970                     (conditional->body.conditional.value != virtual_root)) {
2971                         (void) SETVAR(conditional->body.conditional.name,
2972                                       conditional->body.conditional.value,
2973                                       (Boolean) conditional->body.conditional.append);
2974                 }
2975                 cond_name = ALLOC(Chain);
2976                 cond_name->name = conditional->body.conditional.name;
2977         }
2978         /* Put this target on the front of the chain of conditional targets */
2979         cond_chain = ALLOC(Chain);
2980         cond_chain->name = target;
2981         cond_chain->next = conditional_targets;
2982         conditional_targets = cond_chain;
2983         conditional_macro_used = saved_conditional_macro_used;


2999  */
3000 void
3001 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3002 {
3003         register Property       this_conditional;
3004         Chain                   cond_chain;
3005 
3006         if (target->dont_activate_cond_values) {
3007                 return;
3008         }
3009 
3010         /* Scan the list of conditional properties and restore the old value */
3011         /* to each one Reverse the order relative to when we assigned macros */
3012         this_conditional = get_prop(conditional->next, conditional_prop);
3013         if (this_conditional != NULL) {
3014                 reset_locals(target, old_locals, this_conditional, index+1);
3015         } else {
3016                 /* Remove conditional target from chain */
3017                 if (conditional_targets == NULL ||
3018                     conditional_targets->name != target) {
3019                         warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
3020                 } else {
3021                         cond_chain = conditional_targets->next;
3022                         retmem_mb((caddr_t) conditional_targets);
3023                         conditional_targets = cond_chain;
3024                 }
3025         }
3026         get_prop(conditional->body.conditional.name->prop,
3027                  macro_prop)->body.macro = old_locals[index].body.macro;
3028         if (conditional->body.conditional.name == virtual_root) {
3029                 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3030         }
3031         if (debug_level > 1) {
3032                 if (old_locals[index].body.macro.value != NULL) {
3033                         (void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
3034                                       recursion_level,
3035                                       "",
3036                                       conditional->body.conditional.name->
3037                                       string_mb,
3038                                       old_locals[index].body.macro.value->
3039                                       string_mb);
3040                 } else {
3041                         (void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
3042                                       recursion_level,
3043                                       "",
3044                                       conditional->body.conditional.name->
3045                                       string_mb);
3046                 }
3047         }
3048 }
3049 
3050 /*
3051  *      check_auto_dependencies(target, auto_count, automatics)
3052  *
3053  *      Returns true if the target now has a dependency
3054  *      it didn't previously have (saved on automatics).
3055  *
3056  *      Return value:
3057  *                              true if new dependency found
3058  *
3059  *      Parameters:
3060  *              target          Target we check
3061  *              auto_count      Number of old automatic vars