"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sunpro/Make/bin/make/common/read2.cc" (6 Sep 2021, 56302 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "read2.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-09-01_vs_2021-09-18 or 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * This file and its contents are supplied under the terms of the
    5  * Common Development and Distribution License ("CDDL"), version 1.0.
    6  * You may use this file only in accordance with the terms of version
    7  * 1.0 of the CDDL.
    8  *
    9  * A full copy of the text of the CDDL should have accompanied this
   10  * source.  A copy of the CDDL is also available via the Internet at
   11  * http://www.opensource.org/licenses/cddl1.txt
   12  * See the License for the specific language governing permissions
   13  * and limitations under the License.
   14  *
   15  * When distributing Covered Code, include this CDDL HEADER in each
   16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   17  * If applicable, add the following below this CDDL HEADER, with the
   18  * fields enclosed by brackets "[]" replaced with your own identifying
   19  * information: Portions Copyright [yyyy] [name of copyright owner]
   20  *
   21  * CDDL HEADER END
   22  */
   23 /*
   24  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
   25  * Use is subject to license terms.
   26  */
   27 /*
   28  * @(#)read2.cc 1.53 06/12/12
   29  */
   30 
   31 #pragma ident   "@(#)read2.cc   1.53    06/12/12"
   32 
   33 /*
   34  * Copyright 2017-2021 J. Schilling
   35  *
   36  * @(#)read2.cc 1.26 21/09/06 2017-2021 J. Schilling
   37  */
   38 #include <schily/mconfig.h>
   39 #ifndef lint
   40 static  UConst char sccsid[] =
   41     "@(#)read2.cc   1.26 21/09/06 2017-2021 J. Schilling";
   42 #endif
   43 
   44 /*
   45  *  read.c
   46  *
   47  *  This file contains the makefile reader.
   48  */
   49 
   50 /*
   51  * Included files
   52  */
   53 #include <mk/defs.h>
   54 #include <mksh/dosys.h>     /* sh_command2string() */
   55 #include <mksh/macro.h>     /* expand_value() */
   56 #include <mksh/misc.h>      /* retmem() */
   57 #include <stdarg.h>     /* va_list, va_start(), va_end() */
   58 
   59 #include <schily/stdio.h>
   60 #include <schily/wchar.h>
   61 #include <schily/schily.h>
   62 
   63 /*
   64  * We cannot use "using std::wcsdup" as wcsdup() is not always
   65  * in the std namespace.
   66  * The Sun CC compiler in version 4 does not suport using namespace std;
   67  * so be careful.
   68  */
   69 #if !defined(__SUNPRO_CC_COMPAT) || __SUNPRO_CC_COMPAT >= 5
   70 using namespace std;        /* needed for wcsdup() */
   71 #endif
   72 
   73 /*
   74  * Defined macros
   75  */
   76 
   77 /*
   78  * typedefs & structs
   79  */
   80 
   81 /*
   82  * Static variables
   83  */
   84 static  Boolean     built_last_make_run_seen;
   85 
   86 /*
   87  * File table of contents
   88  */
   89 static  Name_vector enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names);
   90 extern  Name        normalize_name(register wchar_t *name_string, register int length);
   91 static  void        read_suffixes_list(register Name_vector depes);
   92 static  void        make_relative(wchar_t *to, wchar_t *result);
   93 static  void        print_rule(register Cmd_line command);
   94 static  void        sh_transform(Name *name, Name *value);
   95 
   96 
   97 /*
   98  *  enter_name(string, tail_present, string_start, string_end,
   99  *        current_names, extra_names, target_group_seen)
  100  *
  101  *  Take one string and enter it as a name. The string is passed in
  102  *  two parts. A make string and possibly a C string to append to it.
  103  *  The result is stuffed in the vector current_names.
  104  *  extra_names points to a vector that is used if current_names overflows.
  105  *  This is allocad in the calling routine.
  106  *  Here we handle the "lib.a[members]" notation.
  107  *
  108  *  Return value:
  109  *              The name vector that was used
  110  *
  111  *  Parameters:
  112  *      tail_present    Indicates if both C and make string was passed
  113  *      string_start    C string
  114  *      string_end  Pointer to char after last in C string
  115  *      string      make style string with head of name
  116  *      current_names   Vector to deposit the name in
  117  *      extra_names Where to get next name vector if we run out
  118  *      target_group_seen Pointer to boolean that is set if "+" is seen
  119  *
  120  *  Global variables used:
  121  *      makefile_type   When we read a report file we normalize paths
  122  *      plus        Points to the Name "+"
  123  */
  124 
  125 Name_vector
  126 enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen)
  127 {
  128     Name            name;
  129     register wchar_t    *cp;
  130     wchar_t         ch;
  131 
  132     /* If we were passed a separate tail of the name we append it to the */
  133     /* make string with the rest of it */
  134     if (tail_present) {
  135         append_string(string_start, string, string_end - string_start);
  136         string_start = string->buffer.start;
  137         string_end = string->text.p;
  138     }
  139     ch = *string_end;
  140     *string_end = (int) nul_char;
  141     /*
  142      * Check if there are any ( or [ that are not prefixed with $.
  143      * If there are, we have to deal with the lib.a(members) format.
  144      */
  145     for (cp = (wchar_t *) wcschr(string_start, (int) parenleft_char);
  146          cp != NULL;
  147          cp = (wchar_t *) wcschr(cp + 1, (int) parenleft_char)) {
  148         if (*(cp - 1) != (int) dollar_char) {
  149             *string_end = ch;
  150             return enter_member_name(string_start,
  151                          cp,
  152                          string_end,
  153                          current_names,
  154                          extra_names);
  155         }
  156     }
  157     *string_end = ch;
  158 
  159     if (makefile_type == reading_cpp_file) {
  160         /* Remove extra ../ constructs if we are reading from a report file */
  161         name = normalize_name(string_start, string_end - string_start);
  162     } else {
  163         /*
  164          * /tolik, fix bug 1197477/
  165          * Normalize every target name before entering.
  166          * ..//obj/a.o and ../obj//a.o are not two different targets.
  167          * There is only one target ../obj/a.o
  168          */
  169         /*name = GETNAME(string_start, string_end - string_start);*/
  170         name = normalize_name(string_start, string_end - string_start);
  171     }
  172 
  173     /* Internalize the name. Detect the name "+" (target group here) */
  174 if(current_names->used != 0 && current_names->names[current_names->used-1] == plus) {
  175     if(name == plus) {
  176         return current_names;
  177     }
  178 }
  179     /* If the current_names vector is full we patch in the one from */
  180     /* extra_names */
  181     if (current_names->used == VSIZEOF(current_names->names)) {
  182         if (current_names->next != NULL) {
  183             current_names = current_names->next;
  184         } else {
  185             current_names->next = *extra_names;
  186             *extra_names = NULL;
  187             current_names = current_names->next;
  188             current_names->used = 0;
  189             current_names->next = NULL;
  190         }
  191     }
  192     current_names->target_group[current_names->used] = NULL;
  193     current_names->names[current_names->used++] = name;
  194     if (name == plus) {
  195         *target_group_seen = true;
  196     }
  197     if (tail_present && string->free_after_use) {
  198         retmem(string->buffer.start);
  199     }
  200     return current_names;
  201 }
  202 
  203 /*
  204  *  enter_member_name(lib_start, member_start, string_end,
  205  *        current_names, extra_names)
  206  *
  207  *  A string has been found to contain member names.
  208  *  (The "lib.a[members]" and "lib.a(members)" notation)
  209  *  Handle it pretty much as enter_name() does for simple names.
  210  *
  211  *  Return value:
  212  *              The name vector that was used
  213  *
  214  *  Parameters:
  215  *      lib_start   Points to the of start of "lib.a(member.o)"
  216  *      member_start    Points to "member.o" from above string.
  217  *      string_end  Points to char after last of above string.
  218  *      current_names   Vector to deposit the name in
  219  *      extra_names Where to get next name vector if we run out
  220  *
  221  *  Global variables used:
  222  */
  223 static Name_vector
  224 enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names)
  225 {
  226     register Boolean    entry = false;
  227     wchar_t         buffer[STRING_BUFFER_LENGTH];
  228     Name            lib;
  229     Name            member;
  230     Name            name;
  231     Property        prop;
  232     wchar_t         *memberp;
  233     wchar_t         *q;
  234     register int        paren_count;
  235     register Boolean    has_dollar;
  236     register wchar_t    *cq;
  237     Name            long_member_name = NULL;
  238 
  239     /* Internalize the name of the library */
  240     lib = GETNAME(lib_start, member_start - lib_start);
  241     lib->is_member = true;
  242     member_start++;
  243     if (*member_start == (int) parenleft_char) {
  244         /* This is really the "lib.a((entries))" format */
  245         entry = true;
  246         member_start++;
  247     }
  248     /* Move the library name to the buffer where we intend to build the */
  249     /* "lib.a(member)" for each member */
  250     (void) wcsncpy(buffer, lib_start, member_start - lib_start);
  251     memberp = buffer + (member_start-lib_start);
  252     while (1) {
  253         long_member_name = NULL;
  254         /* Skip leading spaces */
  255         for (;
  256              (member_start < string_end) && iswspace(*member_start);
  257              member_start++);
  258         /* Find the end of the member name. Allow nested (). Detect $*/
  259         for (cq = memberp, has_dollar = false, paren_count = 0;
  260              (member_start < string_end) &&
  261              ((*member_start != (int) parenright_char) ||
  262               (paren_count > 0)) &&
  263              !iswspace(*member_start);
  264              *cq++ = *member_start++) {
  265             switch (*member_start) {
  266             case parenleft_char:
  267                 paren_count++;
  268                 break;
  269             case parenright_char:
  270                 paren_count--;
  271                 break;
  272             case dollar_char:
  273                 has_dollar = true;
  274             }
  275         }
  276         /* Internalize the member name */
  277         member = GETNAME(memberp, cq - memberp);
  278         *cq = 0;
  279         if ((q = (wchar_t *) wcsrchr(memberp, (int) slash_char)) == NULL) {
  280             q = memberp;
  281         }
  282         if ((cq - q > (int) ar_member_name_len) &&
  283             !has_dollar) {
  284             *cq++ = (int) parenright_char;
  285             if (entry) {
  286                 *cq++ = (int) parenright_char;
  287             }
  288             long_member_name = GETNAME(buffer, cq - buffer);
  289             cq = q + (int) ar_member_name_len;
  290         }
  291         *cq++ = (int) parenright_char;
  292         if (entry) {
  293             *cq++ = (int) parenright_char;
  294         }
  295         /* Internalize the "lib.a(member)" notation for this member */
  296         name = GETNAME(buffer, cq - buffer);
  297         name->is_member = lib->is_member;
  298         if (long_member_name != NULL) {
  299             prop = append_prop(name, long_member_name_prop);
  300             name->has_long_member_name = true;
  301             prop->body.long_member_name.member_name =
  302               long_member_name;
  303         }
  304         /* And add the member prop */
  305         prop = append_prop(name, member_prop);
  306         prop->body.member.library = lib;
  307         if (entry) {
  308             /* "lib.a((entry))" notation */
  309             prop->body.member.entry = member;
  310             prop->body.member.member = NULL;
  311         } else {
  312             /* "lib.a(member)" Notation */
  313             prop->body.member.entry = NULL;
  314             prop->body.member.member = member;
  315         }
  316         /* Handle overflow of current_names */
  317         if (current_names->used == VSIZEOF(current_names->names)) {
  318             if (current_names->next != NULL) {
  319                 current_names = current_names->next;
  320             } else {
  321                 if (*extra_names == NULL) {
  322                     current_names =
  323                       current_names->next =
  324                         ALLOC(Name_vector);
  325                 } else {
  326                     current_names =
  327                       current_names->next =
  328                         *extra_names;
  329                     *extra_names = NULL;
  330                 }
  331                 current_names->used = 0;
  332                 current_names->next = NULL;
  333             }
  334         }
  335         current_names->target_group[current_names->used] = NULL;
  336         current_names->names[current_names->used++] = name;
  337         while (iswspace(*member_start)) {
  338             member_start++;
  339         }
  340         /* Check if there are more members */
  341         if ((*member_start == (int) parenright_char) ||
  342             (member_start >= string_end)) {
  343             return current_names;
  344         }
  345     }
  346     /* NOTREACHED */
  347 }
  348 
  349 /*
  350  *  normalize_name(name_string, length)
  351  *
  352  *  Take a namestring and remove redundant ../, // and ./ constructs
  353  *
  354  *  Return value:
  355  *              The normalized name
  356  *
  357  *  Parameters:
  358  *      name_string Path string to normalize
  359  *      length      Length of that string
  360  *
  361  *  Global variables used:
  362  *      dot     The Name ".", compared against
  363  *      dotdot      The Name "..", compared against
  364  */
  365 Name
  366 normalize_name(register wchar_t *name_string, register int length)
  367 {
  368     static Name     dotdot;
  369     register wchar_t    *string = ALLOC_WC(length + 1);
  370     register wchar_t    *string2;
  371     register wchar_t    *cdp;
  372     wchar_t         *current_component;
  373     Name            name;
  374     register int        count;
  375 
  376     if (dotdot == NULL) {
  377         MBSTOWCS(wcs_buffer, "..");
  378         dotdot = GETNAME(wcs_buffer, FIND_LENGTH);
  379     }
  380 
  381     /*
  382      * Copy string removing ./ and //.
  383      * First strip leading ./
  384      */
  385     while ((length > 1) &&
  386            (name_string[0] == (int) period_char) &&
  387            (name_string[1] == (int) slash_char)) {
  388         name_string += 2;
  389         length -= 2;
  390         while ((length > 0) && (name_string[0] == (int) slash_char)) {
  391             name_string++;
  392             length--;
  393         }
  394     }
  395     /* Then copy the rest of the string removing /./ & // */
  396     cdp = string;
  397     while (length > 0) {
  398         if (((length > 2) &&
  399              (name_string[0] == (int) slash_char) &&
  400              (name_string[1] == (int) period_char) &&
  401              (name_string[2] == (int) slash_char)) ||
  402             ((length == 2) &&
  403              (name_string[0] == (int) slash_char) &&
  404              (name_string[1] == (int) period_char))) {
  405             name_string += 2;
  406             length -= 2;
  407             continue;
  408         }
  409         if ((length > 1) &&
  410             (name_string[0] == (int) slash_char) &&
  411             (name_string[1] == (int) slash_char)) {
  412             name_string++;
  413             length--;
  414             continue;
  415         }
  416         *cdp++ = *name_string++;
  417         length--;
  418     }
  419     *cdp = (int) nul_char;
  420     /*
  421      * Now scan for <name>/../ and remove such combinations iff <name>
  422      * is not another ..
  423      * Each time something is removed, the whole process is restarted.
  424      */
  425 removed_one:
  426     name_string = string;
  427     string2 = name_string;      /*save for free*/
  428     current_component =
  429       cdp =
  430         string =
  431           ALLOC_WC((length = wcslen(name_string)) + 1);
  432     while (length > 0) {
  433         if (((length > 3) &&
  434              (name_string[0] == (int) slash_char) &&
  435              (name_string[1] == (int) period_char) &&
  436              (name_string[2] == (int) period_char) &&
  437              (name_string[3] == (int) slash_char)) ||
  438             ((length == 3) &&
  439              (name_string[0] == (int) slash_char) &&
  440              (name_string[1] == (int) period_char) &&
  441              (name_string[2] == (int) period_char))) {
  442             /* Positioned on the / that starts a /.. sequence */
  443             if (((count = cdp - current_component) != 0) &&
  444                 (exists(name = GETNAME(string, cdp - string)) > file_doesnt_exist) &&
  445                 (!name->stat.is_sym_link)) {
  446                 name = GETNAME(current_component, count);
  447                 if(name != dotdot) {
  448                     cdp = current_component;
  449                     name_string += 3;
  450                     length -= 3;
  451                     if (length > 0) {
  452                         name_string++;  /* skip slash */
  453                         length--;
  454                         while (length > 0) {
  455                             *cdp++ = *name_string++;
  456                             length--;
  457                         }
  458                     }
  459                     *cdp = (int) nul_char;
  460                     retmem(string2);
  461                     goto removed_one;
  462                 }
  463             }
  464         }
  465         if ((*cdp++ = *name_string++) == (int) slash_char) {
  466             current_component = cdp;
  467         }
  468         length--;
  469     }
  470     *cdp = (int) nul_char;
  471     if (string[0] == (int) nul_char) {
  472         name = dot;
  473     } else {
  474         name = GETNAME(string, FIND_LENGTH);
  475     }
  476     retmem(string);
  477     retmem(string2);
  478     return name;
  479 }
  480 
  481 /*
  482  *  find_target_groups(target_list)
  483  *
  484  *  If a "+" was seen when the target list was scanned we need to extract
  485  *  the groups. Each target in the name vector that is a member of a
  486  *  group gets a pointer to a chain of all the members stuffed in its
  487  *  target_group vector slot
  488  *
  489  *  Parameters:
  490  *      target_list The list of targets that contains "+"
  491  *
  492  *  Global variables used:
  493  *      plus        The Name "+", compared against
  494  */
  495 Chain
  496 find_target_groups(register Name_vector target_list, register int i, Boolean reset)
  497 {
  498     static Chain        target_group = NULL;
  499     static Chain        tail_target_group = NULL;
  500     static Name     *next;
  501     static Boolean  clear_target_group = false;
  502 
  503     if (reset) {
  504         target_group = NULL;
  505         tail_target_group = NULL;
  506         clear_target_group = false;
  507     }
  508 
  509     /* Scan the list of targets */
  510     /* If the previous target terminated a group */
  511     /* we flush the pointer to that member chain */
  512     if (clear_target_group) {
  513         clear_target_group = false;
  514         target_group = NULL;
  515     }
  516     /* Pick up a pointer to the cell with */
  517     /* the next target */
  518     if (i + 1 != target_list->used) {
  519         next = &target_list->names[i + 1];
  520     } else {
  521         next = (target_list->next != NULL) ?
  522           &target_list->next->names[0] : NULL;
  523     }
  524     /* We have four states here :
  525      *  0:  No target group started and next element is not "+" 
  526      *      This is not interesting.
  527      *  1:  A target group is being built and the next element 
  528      *      is not "+". This terminates the group.
  529      *  2:  No target group started and the next member is "+" 
  530      *      This is the first target in a group.
  531      *  3:  A target group started and the next member is a "+" 
  532      *      The group continues.
  533      */
  534     switch ((target_group ? 1 : 0) +
  535         (next && (*next == plus) ?
  536          2 : 0)) {
  537           case 0:   /* Not target_group */
  538         break;
  539           case 1:   /* Last group member */
  540         /* We need to keep this pointer so */
  541         /* we can stuff it for last member */
  542         clear_target_group = true;
  543         /* fall into */
  544           case 3:   /* Middle group member */
  545         /* Add this target to the */
  546         /* current chain */
  547         tail_target_group->next = ALLOC(Chain);
  548         tail_target_group = tail_target_group->next;
  549         tail_target_group->next = NULL;
  550         tail_target_group->name = target_list->names[i];
  551         break;
  552           case 2:   /* First group member */
  553         /* Start a new chain */
  554         target_group = tail_target_group = ALLOC(Chain);
  555         target_group->next = NULL;
  556         target_group->name = target_list->names[i];
  557         break;
  558     }
  559     /* Stuff the current chain, if any, in the */
  560     /* targets group slot */
  561     target_list->target_group[i] = target_group;
  562     if ((next != NULL) &&
  563         (*next == plus)) {
  564         *next = NULL;
  565     }
  566     return (tail_target_group);
  567 }
  568 
  569 /*
  570  *  enter_dependencies(target, target_group, depes, command, separator)
  571  *
  572  *  Take one target and a list of dependencies and process the whole thing.
  573  *  The target might be special in some sense in which case that is handled
  574  *
  575  *  Parameters:
  576  *      target      The target we want to enter
  577  *      target_group    Non-NULL if target is part of a group this time
  578  *      depes       A list of dependencies for the target
  579  *      command     The command the target should be entered with
  580  *      separator   Indicates if this is a ":" or a "::" rule
  581  *
  582  *  Static variables used:
  583  *      built_last_make_run_seen If the previous target was
  584  *                  .BUILT_LAST_MAKE_RUN we say to rewrite
  585  *                  the state file later on
  586  *
  587  *  Global variables used:
  588  *      command_changed Set to indicate if .make.state needs rewriting
  589  *      default_target_to_build Set to the target if reading makefile
  590  *                  and this is the first regular target
  591  *      force       The Name " FORCE", used with "::" targets
  592  *      makefile_type   We do different things for makefile vs. report
  593  *      not_auto    The Name ".NOT_AUTO", compared against
  594  *      recursive_name  The Name ".RECURSIVE", compared against
  595  *      temp_file_number Used to figure out when to clear stale
  596  *                  automatic dependencies
  597  *      trace_reader    Indicates that we should echo stuff we read
  598  */
  599 void
  600 enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator)
  601 {
  602     register int        i;
  603     register Property   line;
  604     Name            name;
  605     Name            directory;
  606     wchar_t         *namep;
  607     char            *mb_namep;
  608     Dependency      dp;
  609     Dependency      *dpp;
  610     Property        line2;
  611     wchar_t         relative[MAXPATHLEN];
  612     register int        recursive_state;
  613     Boolean         register_as_auto;
  614     Boolean         not_auto_found;
  615     char            *slash;
  616     Wstring         depstr;
  617 
  618     /* Check if this is a .RECURSIVE line */
  619     if ((depes->used >= 3) &&
  620         (depes->names[0] == recursive_name)) {
  621 #ifdef NSE
  622                 nse_did_recursion= true;
  623 #endif
  624         target->has_recursive_dependency = true;
  625         depes->names[0] = NULL;
  626         recursive_state = 0;
  627         dp = NULL;
  628         dpp = &dp;
  629         /* Read the dependencies. They are "<directory> <target-made>*/
  630         /* <makefile>*" */
  631         for (; depes != NULL; depes = depes->next) {
  632             for (i = 0; i < depes->used; i++) {
  633                 if (depes->names[i] != NULL) {
  634                     switch (recursive_state++) {
  635                     case 0: /* Directory */
  636                     {
  637                         depstr.init(depes->names[i]);
  638                         make_relative(depstr.get_string(),
  639                                   relative);
  640                         directory =
  641                           GETNAME(relative,
  642                               FIND_LENGTH);
  643                     }
  644                         break;
  645                     case 1: /* Target */
  646                         name = depes->names[i];
  647                         break;
  648                     default:    /* Makefiles */
  649                         *dpp = ALLOC(Dependency);
  650                         (*dpp)->next = NULL;
  651                         (*dpp)->name = depes->names[i];
  652                         (*dpp)->automatic = false;
  653                         (*dpp)->stale = false;
  654                         (*dpp)->built = false;
  655                         dpp = &((*dpp)->next);
  656                         break;
  657                     }
  658                 }
  659             }
  660         }
  661         /* Check if this recursion already has been reported else */
  662         /* enter the recursive prop for the target */
  663         /* The has_built flag is used to tell if this .RECURSIVE */
  664         /* was discovered from this run (read from a tmp file) */
  665         /* or was from discovered from the original .make.state */
  666         /* file */
  667         for (line = get_prop(target->prop, recursive_prop);
  668              line != NULL;
  669              line = get_prop(line->next, recursive_prop)) {
  670             if ((line->body.recursive.directory == directory) &&
  671                 (line->body.recursive.target == name)) {
  672                 line->body.recursive.makefiles = dp;
  673                 line->body.recursive.has_built = 
  674                   (Boolean)
  675                     (makefile_type == reading_cpp_file);
  676                 return;
  677             }
  678         }
  679         line2 = append_prop(target, recursive_prop);
  680         line2->body.recursive.directory = directory;
  681         line2->body.recursive.target = name;
  682         line2->body.recursive.makefiles = dp;
  683         line2->body.recursive.has_built = 
  684             (Boolean) (makefile_type == reading_cpp_file);
  685         line2->body.recursive.in_depinfo = false;
  686         return;
  687     }
  688     /* If this is the first target that doesnt start with a "." in the */
  689     /* makefile we remember that */
  690     Wstring tstr(target);
  691     wchar_t * wcb = tstr.get_string();
  692     if ((makefile_type == reading_makefile) &&
  693         (default_target_to_build == NULL) &&
  694         ((wcb[0] != (int) period_char) ||
  695          wcschr(wcb, (int) slash_char))) {
  696 
  697 /* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO):
  698 ** The target with empty name cannot be default_target_to_build
  699 */
  700         if (target->hash.length != 0)
  701             default_target_to_build = target;
  702     }
  703     /* Check if the line is ":" or "::" */
  704     if (makefile_type == reading_makefile) {
  705         if (target->colons == no_colon) {
  706             target->colons = separator;
  707         } else {
  708             if (target->colons != separator) {
  709                 fatal_reader(gettext(":/:: conflict for target `%s'"),
  710                          target->string_mb);
  711             }
  712         }
  713         if (target->colons == two_colon) {
  714             if (depes->used == 0) {
  715                 /* If this is a "::" type line with no */
  716                 /* dependencies we add one "FRC" type */
  717                 /* dependency for free */
  718                 depes->used = 1; /* Force :: targets with no
  719                           * depes to always run */
  720                 depes->names[0] = force;
  721             }
  722             /* Do not delete "::" type targets when interrupted */
  723             target->stat.is_precious = true;
  724             /*
  725              * Build a synthetic target "<number>%target"
  726              * for "target".
  727              */
  728             mb_namep = getmem((int) (strlen(target->string_mb) + 10));
  729             namep = ALLOC_WC((int) (target->hash.length + 10));
  730             slash = strrchr(target->string_mb, (int) slash_char);
  731             if (slash == NULL) {
  732                 (void) sprintf(mb_namep,
  733                             "%d@%s",
  734                             target->colon_splits++,
  735                             target->string_mb);
  736             } else {
  737                 *slash = 0;
  738                 (void) sprintf(mb_namep,
  739                             "%s/%d@%s",
  740                             target->string_mb,
  741                             target->colon_splits++,
  742                             slash + 1);
  743                 *slash = (int) slash_char;
  744             }
  745             MBSTOWCS(namep, mb_namep);
  746             retmem_mb(mb_namep);
  747             name = GETNAME(namep, FIND_LENGTH);
  748             retmem(namep);
  749             if (trace_reader) {
  750                 (void) printf("%s:\t", target->string_mb);
  751             }
  752             /* Make "target" depend on "<number>%target */
  753             line2 = maybe_append_prop(target, line_prop);
  754             enter_dependency(line2, name, true);
  755             line2->body.line.target = target;
  756             /* Put a prop on "<number>%target that makes */
  757             /* appear as "target" */
  758             /* when it is processed */
  759             maybe_append_prop(name, target_prop)->
  760               body.target.target = target;
  761             target->is_double_colon_parent = true;
  762             name->is_double_colon = true;
  763             name->has_target_prop = true;
  764             if (trace_reader) {
  765                 (void) printf("\n");
  766             }
  767             (target = name)->stat.is_file = true;
  768         }
  769     }
  770     /* This really is a regular dependency line. Just enter it */
  771     line = maybe_append_prop(target, line_prop);
  772     line->body.line.target = target;
  773     /* Depending on what kind of makefile we are reading we have to */
  774     /* treat things differently */
  775     switch (makefile_type) {
  776     case reading_makefile:
  777         /* Reading regular makefile. Just notice whether this */
  778         /* redefines the rule for the  target */
  779         if (command != NULL) {
  780             if (line->body.line.command_template != NULL) {
  781                 line->body.line.command_template_redefined =
  782                   true;
  783                 if ((wcb[0] == (int) period_char) &&
  784                     !wcschr(wcb, (int) slash_char)) {
  785                     line->body.line.command_template =
  786                       command;
  787                 }
  788             } else {
  789                 line->body.line.command_template = command;
  790             }
  791         } else {
  792             if ((wcb[0] == (int) period_char) &&
  793                 !wcschr(wcb, (int) slash_char)) {
  794                 line->body.line.command_template = command;
  795             }
  796         }
  797         break;
  798     case rereading_statefile:
  799         /* Rereading the statefile. We only enter thing that changed */
  800         /* since the previous time we read it */
  801         if (!built_last_make_run_seen) {
  802             for (Cmd_line next, cmd = command; cmd != NULL; cmd = next) {
  803                 next = cmd->next;
  804                 free(cmd);
  805             }
  806             return;
  807         }
  808         built_last_make_run_seen = false;
  809         command_changed = true;
  810         target->ran_command = true;
  811         /* FALLTHRU */
  812     case reading_statefile:
  813         /* Reading the statefile for the first time. Enter the rules */
  814         /* as "Commands used" not "templates to use" */
  815         if (command != NULL) {
  816             for (Cmd_line next, cmd = line->body.line.command_used;
  817                  cmd != NULL; cmd = next) {
  818                 next = cmd->next;
  819                 free(cmd);
  820             }
  821             line->body.line.command_used = command;
  822         }
  823         /* FALLTHRU */
  824     case reading_cpp_file:
  825         /* Reading report file from programs that reports */
  826         /* dependencies. If this is the first time the target is */
  827         /* read from this reportfile we clear all old */
  828         /* automatic depes */
  829         if (target->temp_file_number == temp_file_number) {
  830             break;
  831         }
  832         target->temp_file_number = temp_file_number;
  833         command_changed = true;
  834         if (line != NULL) {
  835             for (dp = line->body.line.dependencies;
  836                  dp != NULL;
  837                  dp = dp->next) {
  838                 if (dp->automatic) {
  839                     dp->stale = true;
  840                 }
  841             }
  842         }
  843         break;
  844     default:
  845         fatal_reader(gettext("Internal error. Unknown makefile type %d"),
  846                  makefile_type);
  847     }
  848     /* A target may only be involved in one target group */
  849     if (line->body.line.target_group != NULL) {
  850         if (target_group != NULL) {
  851             fatal_reader(gettext("Too many target groups for target `%s'"),
  852                      target->string_mb);
  853         }
  854     } else {
  855         line->body.line.target_group = target_group;
  856     }
  857 
  858     if (trace_reader) {
  859         (void) printf("%s:\t", target->string_mb);
  860     }
  861     /* Enter the dependencies */
  862     register_as_auto = BOOLEAN(makefile_type != reading_makefile);
  863     not_auto_found = false;
  864     for (;
  865          (depes != NULL) && !not_auto_found;
  866          depes = depes->next) {
  867         for (i = 0; i < depes->used; i++) {
  868             /* the dependency .NOT_AUTO signals beginning of
  869              * explicit dependancies which were put at end of
  870              * list in .make.state file - we stop entering
  871              * dependencies at this point
  872              */
  873             if (depes->names[i] == not_auto) {
  874                 not_auto_found = true;
  875                 break;
  876             }
  877             enter_dependency(line,
  878                      depes->names[i],
  879                      register_as_auto);
  880         }
  881     }
  882     if (trace_reader) {
  883         (void) printf("\n");
  884         print_rule(command);
  885     }
  886 }
  887 
  888 /*
  889  *  enter_dependency(line, depe, automatic)
  890  *
  891  *  Enter one dependency. Do not enter duplicates.
  892  *
  893  *  Parameters:
  894  *      line        The line block that the dependeny is
  895  *              entered for
  896  *      depe        The dependency to enter
  897  *      automatic   Used to set the field "automatic"
  898  *
  899  *  Global variables used:
  900  *      makefile_type   We do different things for makefile vs. report
  901  *      trace_reader    Indicates that we should echo stuff we read
  902  *      wait_name   The Name ".WAIT", compared against
  903  */
  904 void
  905 enter_dependency(Property line, register Name depe, Boolean automatic)
  906 {
  907     register Dependency dp;
  908     register Dependency *insert;
  909 
  910     if (trace_reader) {
  911         (void) printf("%s ", depe->string_mb);
  912     }
  913     /* Find the end of the list and check for duplicates */
  914     for (insert = &line->body.line.dependencies, dp = *insert;
  915          dp != NULL;
  916          insert = &dp->next, dp = *insert) {
  917         if ((dp->name == depe) && (depe != wait_name)) {
  918             if (dp->automatic) {
  919                 dp->automatic = automatic;
  920                 if (automatic) {
  921                     dp->built = false;
  922                     depe->stat.is_file = true;
  923 #ifdef NSE
  924                         depe->has_parent= true;
  925                         depe->is_target= true;
  926 #endif
  927                 }
  928             }
  929             dp->stale = false;
  930             return;
  931         }
  932     }
  933     /* Insert the new dependency since we couldnt find it */
  934     dp = *insert = ALLOC(Dependency);
  935     dp->name = depe;
  936     dp->next = NULL;
  937     dp->automatic = automatic;
  938     dp->stale = false;
  939     dp->built = false;
  940     depe->stat.is_file = true;
  941 #ifdef NSE
  942         depe->has_parent= true;
  943         depe->is_target= true;
  944 #endif
  945 
  946     if ((makefile_type == reading_makefile) &&
  947         (line != NULL) &&
  948         (line->body.line.target != NULL)) {
  949         line->body.line.target->has_regular_dependency = true;
  950 #ifdef NSE
  951                 line->body.line.target->is_target= true;
  952 #endif
  953     }
  954 }
  955 
  956 /*
  957  *  enter_percent(target, depes, command)
  958  *
  959  *  Enter "x%y : a%b" type lines
  960  *  % patterns are stored in four parts head and tail for target and source
  961  *
  962  *  Parameters:
  963  *      target      Left hand side of pattern
  964  *      depes       The dependency list with the rh pattern
  965  *      command     The command for the pattern
  966  *
  967  *  Global variables used:
  968  *      empty_name  The Name "", compared against
  969  *      percent_list    The list of all percent rules, added to
  970  *      trace_reader    Indicates that we should echo stuff we read
  971  */
  972 Percent
  973 enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command)
  974 {
  975     register Percent    result = ALLOC(Percent);
  976     register Percent    depe;
  977     register Percent    *depe_tail = &result->dependencies;
  978     register Percent    *insert;
  979     register wchar_t    *cp, *cp1;
  980     Name_vector     nvp;
  981     int         i;
  982     int         pattern;
  983 
  984     result->next = NULL;
  985     result->patterns = NULL;
  986     result->patterns_total = 0;
  987     result->command_template = command;
  988     result->being_expanded = false;
  989     result->name = target;
  990     result->dependencies = NULL;
  991     result->target_group = target_group;
  992 
  993     /* get patterns count */
  994     Wstring wcb(target);
  995     cp = wcb.get_string();
  996     while (true) {
  997         cp = (wchar_t *) wcschr(cp, (int) percent_char);
  998         if (cp != NULL) {
  999             result->patterns_total++;
 1000             cp++;
 1001         } else {
 1002             break;
 1003         }
 1004     }
 1005     result->patterns_total++;
 1006 
 1007     /* allocate storage for patterns */
 1008     result->patterns = (Name *) getmem(sizeof(Name) * result->patterns_total);
 1009 
 1010     /* then create patterns */
 1011     cp = wcb.get_string();
 1012     pattern = 0;
 1013     while (true) {
 1014         cp1 = (wchar_t *) wcschr(cp, (int) percent_char);
 1015         if (cp1 != NULL) {
 1016             result->patterns[pattern] = GETNAME(cp, cp1 - cp);
 1017             cp = cp1 + 1;
 1018             pattern++;
 1019         } else {
 1020             result->patterns[pattern] = GETNAME(cp, (int) target->hash.length - (cp - wcb.get_string()));
 1021             break;
 1022         }
 1023     }
 1024 
 1025     Wstring wcb1;
 1026 
 1027     /* build dependencies list */
 1028     for (nvp = depes; nvp != NULL; nvp = nvp->next) {
 1029         for (i = 0; i < nvp->used; i++) {
 1030             depe = ALLOC(Percent);
 1031             depe->next = NULL;
 1032             depe->patterns = NULL;
 1033             depe->patterns_total = 0;
 1034             depe->name = nvp->names[i];
 1035             depe->dependencies = NULL;
 1036             depe->command_template = NULL;
 1037             depe->being_expanded = false;
 1038             depe->target_group = NULL;
 1039 
 1040             *depe_tail = depe;
 1041             depe_tail = &depe->next;
 1042 
 1043             if (depe->name->percent) {
 1044                 /* get patterns count */
 1045                 wcb1.init(depe->name);
 1046                 cp = wcb1.get_string();
 1047                 while (true) {
 1048                     cp = (wchar_t *) wcschr(cp, (int) percent_char);
 1049                     if (cp != NULL) {
 1050                         depe->patterns_total++;
 1051                         cp++;
 1052                     } else {
 1053                         break;
 1054                     }
 1055                 }
 1056                 depe->patterns_total++;
 1057 
 1058                 /* allocate storage for patterns */
 1059                 depe->patterns = (Name *) getmem(sizeof(Name) * depe->patterns_total);
 1060 
 1061                 /* then create patterns */
 1062                 cp = wcb1.get_string();
 1063                 pattern = 0;
 1064                 while (true) {
 1065                     cp1 = (wchar_t *) wcschr(cp, (int) percent_char);
 1066                     if (cp1 != NULL) {
 1067                         depe->patterns[pattern] = GETNAME(cp, cp1 - cp);
 1068                         cp = cp1 + 1;
 1069                         pattern++;
 1070                     } else {
 1071                         depe->patterns[pattern] = GETNAME(cp, (int) depe->name->hash.length - (cp - wcb1.get_string()));
 1072                         break;
 1073                     }
 1074                 }
 1075             }
 1076         }
 1077     }
 1078 
 1079     /* Find the end of the percent list and append the new pattern */
 1080     for (insert = &percent_list; (*insert) != NULL; insert = &(*insert)->next);
 1081     *insert = result;
 1082 
 1083     if (trace_reader) {
 1084         (void) printf("%s:", result->name->string_mb);
 1085 
 1086         for (depe = result->dependencies; depe != NULL; depe = depe->next) {
 1087             (void) printf(" %s", depe->name->string_mb);
 1088         }
 1089 
 1090         (void) printf("\n");
 1091 
 1092         print_rule(command);
 1093     }
 1094 
 1095     return result;
 1096 }
 1097 
 1098 /*
 1099  *  enter_dyntarget(target)
 1100  *
 1101  *  Enter "$$(MACRO) : b" type lines
 1102  *
 1103  *  Parameters:
 1104  *      target      Left hand side of pattern
 1105  *
 1106  *  Global variables used:
 1107  *      dyntarget_list  The list of all percent rules, added to
 1108  *      trace_reader    Indicates that we should echo stuff we read
 1109  */
 1110 Dyntarget
 1111 enter_dyntarget(register Name target)
 1112 {
 1113     register Dyntarget  result = ALLOC(Dyntarget);
 1114     Dyntarget       p;
 1115     Dyntarget       *insert;
 1116     int             i;
 1117 
 1118     result->next = NULL;
 1119     result->name = target;
 1120 
 1121 
 1122     /* Find the end of the dyntarget list and append the new pattern */
 1123     for (insert = &dyntarget_list, p = *insert;
 1124          p != NULL;
 1125          insert = &p->next, p = *insert);
 1126     *insert = result;
 1127 
 1128     if (trace_reader) {
 1129         (void) printf(NOCATGETS("Dynamic target %s:\n"), result->name->string_mb);
 1130     }
 1131     return( result);
 1132 }
 1133 
 1134 
 1135 /*
 1136  *  special_reader(target, depes, command)
 1137  *
 1138  *  Read the pseudo targets make knows about
 1139  *  This handles the special targets that should not be entered as regular
 1140  *  target/dependency sets.
 1141  *
 1142  *  Parameters:
 1143  *      target      The special target
 1144  *      depes       The list of dependencies it was entered with
 1145  *      command     The command it was entered with
 1146  *
 1147  *  Static variables used:
 1148  *      built_last_make_run_seen Set to indicate .BUILT_LAST... seen
 1149  *
 1150  *  Global variables used:
 1151  *      all_parallel    Set to indicate that everything runs parallel
 1152  *      svr4        Set when ".SVR4" target is read
 1153  *      svr4_name   The Name ".SVR4"
 1154  *      posix       Set when ".POSIX" target is read
 1155  *      posix_name  The Name ".POSIX"
 1156  *      current_make_version The Name "<current version number>"
 1157  *      default_rule    Set when ".DEFAULT" target is read
 1158  *      default_rule_name The Name ".DEFAULT", used for tracing
 1159  *      dot_keep_state  The Name ".KEEP_STATE", used for tracing
 1160  *      ignore_errors   Set if ".IGNORE" target is read
 1161  *      ignore_name The Name ".IGNORE", used for tracing
 1162  *      include_failed_name The Name ".INCLUDE_FAILED", used for automake
 1163  *      keep_state  Set if ".KEEP_STATE" target is read
 1164  *      no_parallel_name The Name ".NO_PARALLEL", used for tracing
 1165  *      notparallel_name The Name ".NOTPARALLEL", used for tracing
 1166  *      notparallel Set if ".NOTPARALLEL" target is read
 1167  *      only_parallel   Set to indicate only some targets runs parallel
 1168  *      parallel_name   The Name ".PARALLEL", used for tracing
 1169  *      phony       The Name ".PHONY", used for tracing
 1170  *      precious    The Name ".PRECIOUS", used for tracing
 1171  *      sccs_get_name   The Name ".SCCS_GET", used for tracing
 1172  *      sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing
 1173  *      get_name    The Name ".GET", used for tracing
 1174  *      sccs_get_rule   Set when ".SCCS_GET" target is read
 1175  *      silent      Set when ".SILENT" target is read
 1176  *      silent_name The Name ".SILENT", used for tracing
 1177  *      trace_reader    Indicates that we should echo stuff we read
 1178  */
 1179 void
 1180 special_reader(Name target, register Name_vector depes, Cmd_line command, Separator separator)
 1181 {
 1182     register int        n;
 1183 
 1184     switch (target->special_reader) {
 1185 
 1186     case svr4_special:
 1187         if (depes->used != 0) {
 1188             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1189                      target->string_mb);
 1190         }
 1191         svr4  = true;
 1192         posix  = false;
 1193         sunpro_compat = false;
 1194         gnu_style = false;
 1195         keep_state = false;
 1196         all_parallel = false;
 1197         only_parallel = false;
 1198         if (trace_reader) {
 1199             (void) printf("%s:\n", svr4_name->string_mb);
 1200         }
 1201         break;
 1202 
 1203     case posix_special:
 1204         /*
 1205          * We cannot do that switch if the mode before was svr4.
 1206          * This is because we did read a different set of builtin
 1207          * rules in that case.
 1208          */
 1209         if(svr4)
 1210           break;
 1211         if (depes->used != 0) {
 1212             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1213                      target->string_mb);
 1214         }
 1215         posix  = true;
 1216         sunpro_compat = false;
 1217         gnu_style = false;
 1218 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1219         job_adjust_posix();     /* DMAKE_ADJUST_MAX_JOBS=M2 */
 1220 #endif
 1221             /* with posix on, use the posix get rule */
 1222         sccs_get_rule = sccs_get_posix_rule;
 1223             /* turn keep state off being SunPro make specific */
 1224         keep_state = false;
 1225         #if defined(SUN5_0)
 1226         /* Use /usr/xpg4/bin/sh on Solaris */
 1227 #ifdef  HAVE__USR_XPG4_BIN_SH
 1228         MBSTOWCS(wcs_buffer, NOCATGETS("/usr/xpg4/bin/sh"));
 1229 #else
 1230 #ifdef  HAVE__OPT_SCHILY_XPG4_BIN_SH
 1231         MBSTOWCS(wcs_buffer, NOCATGETS("/opt/schily/xpg4/bin/sh"));
 1232 #else
 1233 #ifdef  HAVE__BIN_POSIX_SH
 1234         MBSTOWCS(wcs_buffer, NOCATGETS("/bin/posix/sh"));
 1235 #else
 1236         MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh"));
 1237 #endif
 1238 #endif
 1239 #endif
 1240         (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
 1241         #endif
 1242         if (trace_reader) {
 1243             (void) printf("%s:\n", posix_name->string_mb);
 1244         }
 1245         break;
 1246 
 1247     case built_last_make_run_special:
 1248         built_last_make_run_seen = true;
 1249         break;
 1250 
 1251     case default_special:
 1252         if (depes->used != 0) {
 1253             warning(gettext("Illegal dependency list for target `%s'"),
 1254                 target->string_mb);
 1255         }
 1256         default_rule = command;
 1257         if (trace_reader) {
 1258             (void) printf("%s:\n",
 1259                       default_rule_name->string_mb);
 1260             print_rule(command);
 1261         }
 1262         break;
 1263 
 1264 #ifdef NSE
 1265     case derived_src_special:
 1266         for (; depes != NULL; depes= depes->next)
 1267             for (n= 0; n < depes->used; n++) {
 1268                 if (trace_reader)
 1269                     (void)printf("%s:\t%s\n",
 1270                     precious->string_mb,
 1271                     depes->names[n]->string_mb);
 1272                 depes->names[n]->stat.is_derived_src= true;
 1273             };
 1274             break;
 1275 #endif
 1276 
 1277     case ignore_special:
 1278         if ((depes->used != 0) &&(!posix)){
 1279             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1280                      target->string_mb);
 1281         }
 1282         if (depes->used == 0)
 1283         {
 1284            ignore_errors_all = true;
 1285         }
 1286         if(svr4) {
 1287           ignore_errors_all = true;
 1288           break;
 1289         }
 1290         for (; depes != NULL; depes = depes->next) {
 1291             for (n = 0; n < depes->used; n++) {
 1292                 depes->names[n]->ignore_error_mode = true;
 1293             }
 1294         }
 1295         if (trace_reader) {
 1296             (void) printf("%s:\n", ignore_name->string_mb);
 1297         }
 1298         break;
 1299 
 1300 #ifdef  DO_INCLUDE_FAILED
 1301     case include_failed_special:
 1302         if (svr4 || sunpro_compat)
 1303             break;
 1304         if (depes->used != 0) {
 1305             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1306                      target->string_mb);
 1307         }
 1308         if (command) {
 1309             include_failed = true;
 1310             enter_dependencies(target,
 1311                NULL,
 1312                depes,
 1313                command,
 1314                separator);
 1315         }
 1316         break;
 1317 #endif
 1318 
 1319     case keep_state_special:
 1320         if(svr4)
 1321           break;
 1322             /* ignore keep state, being SunPro make specific */
 1323         if(posix)
 1324           break;
 1325         if (depes->used != 0) {
 1326             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1327                      target->string_mb);
 1328         }
 1329         keep_state = true;
 1330         if (trace_reader) {
 1331             (void) printf("%s:\n",
 1332                       dot_keep_state->string_mb);
 1333         }
 1334         break;
 1335 
 1336     case keep_state_file_special:
 1337         if(svr4)
 1338           break;
 1339         if(posix)
 1340           break;
 1341             /* it's not necessary to specify KEEP_STATE, if this 
 1342             ** is given, so set the keep_state.
 1343             */
 1344         keep_state = true;
 1345         if (depes->used != 0) {
 1346            if((!make_state) ||(!strcmp(make_state->string_mb,NOCATGETS(".make.state")))) {
 1347              make_state = depes->names[0];
 1348            }
 1349         }
 1350         break;
 1351     case make_version_special:
 1352         if(svr4)
 1353           break;
 1354         if (depes->used != 1) {
 1355             fatal_reader(gettext("Illegal dependency list for target `%s'"),
 1356                      target->string_mb);
 1357         }
 1358         if (depes->names[0] != current_make_version) {
 1359             /*
 1360              * Special case the fact that version 1.0 and 1.1
 1361              * are identical.
 1362              */
 1363             if (!IS_EQUAL(depes->names[0]->string_mb,
 1364                       NOCATGETS("VERSION-1.1")) ||
 1365                 !IS_EQUAL(current_make_version->string_mb,
 1366                       NOCATGETS("VERSION-1.0"))) {
 1367                 /*
 1368                  * Version mismatches should cause the
 1369                  * .make.state file to be skipped.
 1370                  * This is currently not true - it is read
 1371                  * anyway.
 1372                  */
 1373                 warning(gettext("Version mismatch between current version `%s' and `%s'"),
 1374                     current_make_version->string_mb,
 1375                     depes->names[0]->string_mb);
 1376             }
 1377         }
 1378         break;
 1379 
 1380     case no_parallel_special:
 1381         if(svr4)
 1382           break;
 1383         /* Set the no_parallel bit for all the targets on */
 1384         /* the dependency list */
 1385         if (depes->used == 0) {
 1386             /* only those explicitly made parallel */
 1387             only_parallel = true;
 1388             all_parallel = false;
 1389         }
 1390         for (; depes != NULL; depes = depes->next) {
 1391             for (n = 0; n < depes->used; n++) {
 1392                 if (trace_reader) {
 1393                     (void) printf("%s:\t%s\n",
 1394                               no_parallel_name->string_mb,
 1395                               depes->names[n]->string_mb);
 1396                 }
 1397                 depes->names[n]->no_parallel = true;
 1398                 depes->names[n]->parallel = false;
 1399             }
 1400         }
 1401         break;
 1402 
 1403 #ifdef  DO_NOTPARALLEL
 1404     case notparallel_special:
 1405 
 1406         /* Ignore .NOTPARALLEL if this svr4 or we are on compat mode */
 1407         if (!sunpro_compat && !svr4) {
 1408             if (depes->used != 0) {
 1409                 fatal_reader(gettext(
 1410                     "Illegal dependencies for target `%s'"),
 1411                      target->string_mb);
 1412             }
 1413             notparallel = true;
 1414             if (trace_reader) {
 1415                 (void) printf("%s:\n",
 1416                           notparallel_name->string_mb);
 1417             }
 1418         }
 1419         break;
 1420 #endif
 1421 
 1422     case parallel_special:
 1423         if(svr4)
 1424           break;
 1425         if (depes->used == 0) {
 1426             /* everything runs in parallel */
 1427             all_parallel = true;
 1428             only_parallel = false;
 1429         }
 1430         /* Set the parallel bit for all the targets on */
 1431         /* the dependency list */
 1432         for (; depes != NULL; depes = depes->next) {
 1433             for (n = 0; n < depes->used; n++) {
 1434                 if (trace_reader) {
 1435                     (void) printf("%s:\t%s\n",
 1436                               parallel_name->string_mb,
 1437                               depes->names[n]->string_mb);
 1438                 }
 1439                 depes->names[n]->parallel = true;
 1440                 depes->names[n]->no_parallel = false;
 1441             }
 1442         }
 1443         break;
 1444 
 1445     case localhost_special:
 1446         if(svr4)
 1447           break;
 1448         /* Set the no_parallel bit for all the targets on */
 1449         /* the dependency list */
 1450         if (depes->used == 0) {
 1451             /* only those explicitly made parallel */
 1452             only_parallel = true;
 1453             all_parallel = false;
 1454         }
 1455         for (; depes != NULL; depes = depes->next) {
 1456             for (n = 0; n < depes->used; n++) {
 1457                 if (trace_reader) {
 1458                     (void) printf("%s:\t%s\n",
 1459                               localhost_name->string_mb,
 1460                               depes->names[n]->string_mb);
 1461                 }
 1462                 depes->names[n]->no_parallel = true;
 1463                 depes->names[n]->parallel = false;
 1464                 depes->names[n]->localhost = true;
 1465             }
 1466         }
 1467         break;
 1468 
 1469     case phony_special:
 1470         /*
 1471          * .PHONY is only supported in case we do not emulate the
 1472          * old Sun or SVR4 mode.
 1473          *
 1474          * Otherwise it is ignored as it has been in the
 1475          * old Sun version.
 1476          */
 1477         if (sunpro_compat || svr4)
 1478             break;
 1479 
 1480         /* Set the phony bit for all the targets on */
 1481         /* the dependency list */
 1482         for (; depes != NULL; depes = depes->next) {
 1483             for (n = 0; n < depes->used; n++) {
 1484                 if (trace_reader) {
 1485                     (void) printf("%s:\t%s\n",
 1486                               phony->string_mb,
 1487                               depes->names[n]->string_mb);
 1488                 }
 1489                 depes->names[n]->stat.is_phony = true;
 1490             }
 1491         }
 1492         break;
 1493 
 1494     case precious_special:
 1495         if (depes->used == 0) {
 1496             /* everything is precious      */
 1497             all_precious = true;
 1498         } else {
 1499             all_precious = false;
 1500         }
 1501         if(svr4) {
 1502           all_precious = true;
 1503           break;
 1504         }
 1505         /* Set the precious bit for all the targets on */
 1506         /* the dependency list */
 1507         for (; depes != NULL; depes = depes->next) {
 1508             for (n = 0; n < depes->used; n++) {
 1509                 if (trace_reader) {
 1510                     (void) printf("%s:\t%s\n",
 1511                               precious->string_mb,
 1512                               depes->names[n]->string_mb);
 1513                 }
 1514                 depes->names[n]->stat.is_precious = true;
 1515             }
 1516         }
 1517         break;
 1518 
 1519     case sccs_get_special:
 1520         if (depes->used != 0) {
 1521             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1522                      target->string_mb);
 1523         }
 1524         sccs_get_rule = command;
 1525         sccs_get_org_rule = command;
 1526         if (trace_reader) {
 1527             (void) printf("%s:\n", sccs_get_name->string_mb);
 1528             print_rule(command);
 1529         }
 1530         break;
 1531 
 1532     case sccs_get_posix_special:
 1533         if (depes->used != 0) {
 1534             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1535                      target->string_mb);
 1536         }
 1537         sccs_get_posix_rule = command;
 1538         if (trace_reader) {
 1539             (void) printf("%s:\n", sccs_get_posix_name->string_mb);
 1540             print_rule(command);
 1541         }
 1542         break;
 1543 
 1544     case get_posix_special:
 1545         if (depes->used != 0) {
 1546             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1547                      target->string_mb);
 1548         }
 1549         get_posix_rule = command;
 1550         if (trace_reader) {
 1551             (void) printf("%s:\n", get_posix_name->string_mb);
 1552             print_rule(command);
 1553         }
 1554         break;
 1555 
 1556     case get_special:
 1557         if(!svr4) {
 1558           break;
 1559         }
 1560         if (depes->used != 0) {
 1561             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1562                      target->string_mb);
 1563         }
 1564         get_rule = command;
 1565         sccs_get_rule = command;
 1566         if (trace_reader) {
 1567             (void) printf("%s:\n", get_name->string_mb);
 1568             print_rule(command);
 1569         }
 1570         break;
 1571 
 1572     case silent_special:
 1573         if ((depes->used != 0) && (!posix)){
 1574             fatal_reader(gettext("Illegal dependencies for target `%s'"),
 1575                      target->string_mb);
 1576         }
 1577         if (depes->used == 0)
 1578         {
 1579            silent_all = true;
 1580         }
 1581         if(svr4) {
 1582           silent_all = true;
 1583           break;
 1584         }
 1585         for (; depes != NULL; depes = depes->next) {
 1586             for (n = 0; n < depes->used; n++) {
 1587                 depes->names[n]->silent_mode = true;
 1588             }
 1589         }
 1590         if (trace_reader) {
 1591             (void) printf("%s:\n", silent_name->string_mb);
 1592         }
 1593         break;
 1594 
 1595     case suffixes_special:
 1596         read_suffixes_list(depes);
 1597         break;
 1598 
 1599     default:
 1600 
 1601         fatal_reader(gettext("Internal error: Unknown special reader"));
 1602     }
 1603 }
 1604 
 1605 /*
 1606  *  read_suffixes_list(depes)
 1607  *
 1608  *  Read the special list .SUFFIXES. If it is empty the old list is
 1609  *  cleared. Else the new one is appended. Suffixes with ~ are extracted
 1610  *  and marked.
 1611  *
 1612  *  Parameters:
 1613  *      depes       The list of suffixes
 1614  *
 1615  *  Global variables used:
 1616  *      hashtab     The central hashtable for Names.
 1617  *      suffixes    The list of suffixes, set or appended to
 1618  *      suffixes_name   The Name ".SUFFIXES", used for tracing
 1619  *      trace_reader    Indicates that we should echo stuff we read
 1620  */
 1621 static void
 1622 read_suffixes_list(register Name_vector depes)
 1623 {
 1624     register int        n;
 1625     register Dependency dp;
 1626     register Dependency *insert_dep;
 1627     register Name       np;
 1628     Name            np2;
 1629     register Boolean    first = true;
 1630 
 1631     if (depes->used == 0) {
 1632         /* .SUFFIXES with no dependency list clears the */
 1633         /* suffixes list */
 1634         for (Name_set::iterator np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
 1635                 np->with_squiggle =
 1636                   np->without_squiggle =
 1637                     false;
 1638         }
 1639         suffixes = NULL;
 1640         if (trace_reader) {
 1641             (void) printf("%s:\n", suffixes_name->string_mb);
 1642         }
 1643         return;
 1644     }
 1645     Wstring str;
 1646     /* Otherwise we append to the list */
 1647     for (; depes != NULL; depes = depes->next) {
 1648         for (n = 0; n < depes->used; n++) {
 1649             np = depes->names[n];
 1650             /* Find the end of the list and check if the */
 1651             /* suffix already has been entered */
 1652             for (insert_dep = &suffixes, dp = *insert_dep;
 1653                  dp != NULL;
 1654                  insert_dep = &dp->next, dp = *insert_dep) {
 1655                 if (dp->name == np) {
 1656                     goto duplicate_suffix;
 1657                 }
 1658             }
 1659             if (trace_reader) {
 1660                 if (first) {
 1661                     (void) printf("%s:\t",
 1662                               suffixes_name->string_mb);
 1663                     first = false;
 1664                 }
 1665                 (void) printf("%s ", depes->names[n]->string_mb);
 1666             }
 1667         if(!(posix|svr4)) {
 1668             /* If the suffix is suffixed with "~" we */
 1669             /* strip that and mark the suffix nameblock */
 1670             str.init(np);
 1671             wchar_t * wcb = str.get_string();
 1672             if (wcb[np->hash.length - 1] ==
 1673                 (int) tilde_char) {
 1674                 np2 = GETNAME(wcb,
 1675                           (int)(np->hash.length - 1));
 1676                 np2->with_squiggle = true;
 1677                 if (np2->without_squiggle) {
 1678                     continue;
 1679                 }
 1680                 np = np2;
 1681             }
 1682         }
 1683             np->without_squiggle = true;
 1684             /* Add the suffix to the list */
 1685             dp = *insert_dep = ALLOC(Dependency);
 1686             insert_dep = &dp->next;
 1687             dp->next = NULL;
 1688             dp->name = np;
 1689             dp->built = false;
 1690         duplicate_suffix:;
 1691         }
 1692     }
 1693     if (trace_reader) {
 1694         (void) printf("\n");
 1695     }
 1696 }
 1697 
 1698 /*
 1699  *  make_relative(to, result)
 1700  *
 1701  *  Given a file name compose a relative path name from it to the
 1702  *  current directory.
 1703  *
 1704  *  Parameters:
 1705  *      to      The path we want to make relative
 1706  *      result      Where to put the resulting relative path
 1707  *
 1708  *  Global variables used:
 1709  */
 1710 static void
 1711 make_relative(wchar_t *to, wchar_t *result)
 1712 {
 1713     wchar_t         *from;
 1714     wchar_t         *allocated;
 1715     wchar_t         *cp;
 1716     wchar_t         *tocomp;
 1717     int         ncomps;
 1718     int         i;
 1719     int         len;
 1720 
 1721     /* Check if the path is already relative. */
 1722     if (to[0] != (int) slash_char) {
 1723         (void) wcscpy(result, to);
 1724         return;
 1725     }
 1726 
 1727     MBSTOWCS(wcs_buffer, get_current_path());
 1728     from = allocated = (wchar_t *) wcsdup(wcs_buffer);
 1729 
 1730     /*
 1731      * Find the number of components in the from name.
 1732      * ncomp = number of slashes + 1.
 1733      */
 1734     ncomps = 1;
 1735     for (cp = from; *cp != (int) nul_char; cp++) {
 1736         if (*cp == (int) slash_char) {
 1737             ncomps++;
 1738         }
 1739     }
 1740 
 1741     /*
 1742      * See how many components match to determine how many "..",
 1743      * if any, will be needed.
 1744      */
 1745     result[0] = (int) nul_char;
 1746     tocomp = to;
 1747     while ((*from != (int) nul_char) && (*from == *to)) {
 1748         if (*from == (int) slash_char) {
 1749             ncomps--;
 1750             tocomp = &to[1];
 1751         }
 1752         from++;
 1753         to++;
 1754     }
 1755 
 1756     /*
 1757      * Now for some special cases. Check for exact matches and
 1758      * for either name terminating exactly.
 1759      */
 1760     if (*from == (int) nul_char) {
 1761         if (*to == (int) nul_char) {
 1762             MBSTOWCS(wcs_buffer, ".");
 1763             (void) wcscpy(result, wcs_buffer);
 1764             retmem(allocated);
 1765             return;
 1766         }
 1767         if (*to == (int) slash_char) {
 1768             ncomps--;
 1769             tocomp = &to[1];
 1770         }
 1771     } else if ((*from == (int) slash_char) && (*to == (int) nul_char)) {
 1772         ncomps--;
 1773         tocomp = to;
 1774     }
 1775     /* Add on the ".."s. */
 1776     for (i = 0; i < ncomps; i++) {
 1777         MBSTOWCS(wcs_buffer, "../");
 1778         (void) wcscat(result, wcs_buffer);
 1779     }
 1780 
 1781     /* Add on the remainder of the to name, if any. */
 1782     if (*tocomp == (int) nul_char) {
 1783         len = wcslen(result);
 1784         result[len - 1] = (int) nul_char;
 1785     } else {
 1786         (void) wcscat(result, tocomp);
 1787     }
 1788     retmem(allocated);
 1789     return;
 1790 }
 1791 
 1792 /*
 1793  *  print_rule(command)
 1794  *
 1795  *  Used when tracing the reading of rules
 1796  *
 1797  *  Parameters:
 1798  *      command     Command to print
 1799  *
 1800  *  Global variables used:
 1801  */
 1802 static void
 1803 print_rule(register Cmd_line command)
 1804 {
 1805     for (; command != NULL; command = command->next) {
 1806         (void) printf("\t%s\n", command->command_line->string_mb);
 1807     }
 1808 }
 1809 
 1810 /*
 1811  *  enter_conditional(target, name, value, append)
 1812  *
 1813  *  Enter "target := MACRO= value" constructs
 1814  *
 1815  *  Parameters:
 1816  *      target      The target the macro is for
 1817  *      name        The name of the macro
 1818  *      value       The value for the macro
 1819  *      append      Indicates if the assignment is appending or not
 1820  *
 1821  *  Global variables used:
 1822  *      conditionals    A special Name that stores all conditionals
 1823  *              where the target is a % pattern
 1824  *      trace_reader    Indicates that we should echo stuff we read
 1825  */
 1826 void
 1827 enter_conditional(register Name target, Name name, Name value, register Boolean append)
 1828 {
 1829     register Property   conditional;
 1830     static int      sequence;
 1831     Name            orig_target = target;
 1832 
 1833     if (name == target_arch) {
 1834         enter_conditional(target, virtual_root, virtual_root, false);
 1835     }
 1836 
 1837     if (target->percent) {
 1838         target = conditionals;
 1839     }
 1840     
 1841     if (name->colon) {
 1842         sh_transform(&name, &value);
 1843     }
 1844 
 1845     /* Count how many conditionals we must activate before building the */
 1846     /* target */
 1847     if (target->percent) {
 1848         target = conditionals;
 1849     }
 1850 
 1851     target->conditional_cnt++;
 1852     maybe_append_prop(name, macro_prop)->body.macro.is_conditional = true;
 1853     /* Add the property for the target */
 1854     conditional = append_prop(target, conditional_prop);
 1855     conditional->body.conditional.target = orig_target;
 1856     conditional->body.conditional.name = name;
 1857     conditional->body.conditional.value = value;
 1858     conditional->body.conditional.sequence = sequence++;
 1859     conditional->body.conditional.append = append;
 1860     if (trace_reader) {
 1861         if (value == NULL) {
 1862             (void) printf("%s := %s %c=\n",
 1863                       target->string_mb,
 1864                       name->string_mb,
 1865                       append ?
 1866                       (int) plus_char : (int) space_char);
 1867         } else {
 1868             (void) printf("%s := %s %c= %s\n",
 1869                       target->string_mb,
 1870                       name->string_mb,
 1871                       append ?
 1872                       (int) plus_char : (int) space_char,
 1873                       value->string_mb);
 1874         }
 1875     }
 1876 }
 1877 
 1878 /*
 1879  *  enter_equal(name, value, append)
 1880  *
 1881  *  Enter "MACRO= value" constructs
 1882  *
 1883  *  Parameters:
 1884  *      name        The name of the macro
 1885  *      value       The value for the macro
 1886  *      append      Indicates if the assignment is appending or not
 1887  *      separator   Indicates assignment variants ::=, :::= and ?=
 1888  *
 1889  *  Global variables used:
 1890  *      trace_reader    Indicates that we should echo stuff we read
 1891  */
 1892 void
 1893 enter_equal(Name name, Name value, register Boolean append, Separator separator)
 1894 {
 1895     wchar_t     *string;
 1896     Name        temp;
 1897     Property    prop = NULL;
 1898     String_rec  val;
 1899     wchar_t     buffer[STRING_BUFFER_LENGTH];
 1900     Expand_Type exp_type = deflt_expand;
 1901 
 1902     if (separator == assign_seen ||
 1903         separator == gnu_assign_seen ||
 1904         separator == append_assign_seen ||
 1905         (append && name->stat.macro_type == gnu_assign)) {
 1906         INIT_STRING_FROM_STACK(val, buffer);
 1907         if (separator == assign_seen ||     /* :::= */
 1908             separator == append_assign_seen)    /* +:= */
 1909             exp_type = keep_ddollar;
 1910         expand_value(value, &val, false, exp_type);
 1911         value = GETNAME(val.buffer.start, FIND_LENGTH);
 1912         if (name->stat.macro_type == unknown_macro_type) {
 1913             if (separator == gnu_assign_seen)
 1914                 name->stat.macro_type = gnu_assign;
 1915             else
 1916                 name->stat.macro_type = normal_assign;
 1917         }
 1918             
 1919     } else if (name->colon) {
 1920         sh_transform(&name, &value);
 1921     }
 1922     if (separator == condequal_seen)
 1923         prop = get_prop(name->prop, macro_prop); /* macro is set? */
 1924 
 1925     if (prop == NULL)
 1926         (void) SETVAR(name, value, append);
 1927 
 1928     /* if we're setting FC, we want to set F77 to the same value. */
 1929     Wstring nms(name);
 1930     wchar_t * wcb = nms.get_string();
 1931     string = wcb;
 1932     if (string[0]=='F' &&
 1933         string[1]=='C' &&
 1934         string[2]=='\0') {
 1935         MBSTOWCS(wcs_buffer, NOCATGETS("F77"));
 1936         temp = GETNAME(wcs_buffer, FIND_LENGTH);
 1937         (void) SETVAR(temp, value, append);
 1938 /*
 1939         fprintf(stderr, gettext("warning: FC is obsolete, use F77 instead\n"));
 1940  */
 1941     }
 1942 
 1943     if (trace_reader) {
 1944         char *pre = (char *)" ";
 1945 
 1946         if (append)
 1947             pre = (char *)"+";
 1948         if (separator == assign_seen)
 1949             pre = (char *)":::";
 1950         else if (separator == gnu_assign_seen)
 1951             pre = append ? (char *)"+:" : (char *)"::";
 1952         else if (separator == condequal_seen)
 1953             pre = (char *)"?";
 1954 
 1955         if (value == NULL) {
 1956             (void) printf("%s %s=\n",
 1957                       name->string_mb,
 1958                       pre);
 1959         } else {
 1960             (void) printf("%s %s= %s\n",
 1961                       name->string_mb,
 1962                       pre,
 1963                       value->string_mb);
 1964         }
 1965     }
 1966 }
 1967 
 1968 /*
 1969  *  sh_transform(name, value)
 1970  *
 1971  *  Parameters:
 1972  *      name    The name of the macro we might transform
 1973  *      value   The value to transform
 1974  *
 1975  */
 1976 static void
 1977 sh_transform(Name *name, Name *value)
 1978 {
 1979     /* Check if we need :sh transform */
 1980     wchar_t     *colon;
 1981     String_rec  command;
 1982     String_rec  destination;
 1983     wchar_t     buffer[1000];
 1984     wchar_t     buffer1[1000];
 1985 
 1986     static wchar_t  colon_sh[4];
 1987     static wchar_t  colon_shell[7];
 1988 
 1989     if (colon_sh[0] == (int) nul_char) {
 1990         MBSTOWCS(colon_sh, NOCATGETS(":sh"));
 1991         MBSTOWCS(colon_shell, NOCATGETS(":shell"));
 1992     }
 1993     Wstring nms((*name));
 1994     wchar_t * wcb = nms.get_string();
 1995 
 1996     colon = (wchar_t *) wcsrchr(wcb, (int) colon_char);
 1997     if ((colon != NULL) && (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell))) {
 1998         INIT_STRING_FROM_STACK(destination, buffer);
 1999 
 2000         if(*value == NULL) {
 2001             buffer[0] = 0;
 2002         } else {
 2003             Wstring wcb1((*value));
 2004             if (IS_WEQUAL(colon, colon_shell)) {
 2005                 INIT_STRING_FROM_STACK(command, buffer1);
 2006                 expand_value(*value, &command, false);
 2007             } else {
 2008                 command.text.p = wcb1.get_string() + (*value)->hash.length;
 2009                 command.text.end = command.text.p;
 2010                 command.buffer.start = wcb1.get_string();
 2011                 command.buffer.end = command.text.p;
 2012             }
 2013             sh_command2string(&command, &destination);
 2014         }
 2015 
 2016         (*value) = GETNAME(destination.buffer.start, FIND_LENGTH);
 2017         *colon = (int) nul_char;
 2018         (*name) = GETNAME(wcb, FIND_LENGTH);
 2019         *colon = (int) colon_char;
 2020     }
 2021 }
 2022 
 2023 /*
 2024  *  fatal_reader(format, args...)
 2025  *
 2026  *  Parameters:
 2027  *      format      printf style format string
 2028  *      args        arguments to match the format
 2029  *
 2030  *  Global variables used:
 2031  *      file_being_read Name of the makefile being read
 2032  *      line_number Line that is being read
 2033  *      report_pwd  Indicates whether current path should be shown
 2034  *      temp_file_name  When reading tempfile we report that name
 2035  */
 2036 /*VARARGS*/
 2037 void
 2038 fatal_reader(const char *pattern, ...)
 2039 {
 2040     va_list args;
 2041     char    message[1000];
 2042 
 2043     va_start(args, pattern);
 2044     if (file_being_read != NULL) {
 2045         WCSTOMBS(mbs_buffer, file_being_read);
 2046         if (line_number != 0) {
 2047             (void) sprintf(message,
 2048                        gettext("%s, line %d: %s"),
 2049                        mbs_buffer,
 2050                        line_number,
 2051                        pattern);
 2052         } else {
 2053             (void) sprintf(message,
 2054                        "%s: %s",
 2055                        mbs_buffer,
 2056                        pattern);
 2057         }
 2058         pattern = message;
 2059     }
 2060 
 2061     (void) fflush(stdout);
 2062 #ifdef DISTRIBUTED
 2063     (void) fprintf(stderr, gettext("dmake: Fatal error in reader: "));
 2064 #else
 2065     (void) fprintf(stderr, gettext("make: Fatal error in reader: "));
 2066 #endif
 2067     (void) vfprintf(stderr, pattern, args);
 2068     (void) fprintf(stderr, "\n");
 2069     va_end(args);
 2070 
 2071     if (temp_file_name != NULL) {
 2072         (void) fprintf(stderr,
 2073 #ifdef DISTRIBUTED
 2074                    gettext("dmake: Temp-file %s not removed\n"),
 2075 #else
 2076                    gettext("make: Temp-file %s not removed\n"),
 2077 #endif
 2078                    temp_file_name->string_mb);
 2079         temp_file_name = NULL;
 2080     }
 2081 
 2082     if (report_pwd) {
 2083         (void) fprintf(stderr,
 2084                    gettext("Current working directory %s\n"),
 2085                    get_current_path());
 2086     }
 2087     (void) fflush(stderr);
 2088     exit_status = 1;
 2089     exit(1);
 2090 }
 2091