"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sunpro/Make/bin/make/common/misc.cc" (6 Sep 2021, 29862 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 "misc.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  * @(#)misc.cc 1.50 06/12/12
   29  */
   30 
   31 #pragma ident   "@(#)misc.cc    1.34    95/10/04"
   32 
   33 /*
   34  * Copyright 2017-2021 J. Schilling
   35  *
   36  * @(#)misc.cc  1.24 21/09/06 2017-2021 J. Schilling
   37  */
   38 #include <schily/mconfig.h>
   39 #ifndef lint
   40 static  UConst char sccsid[] =
   41     "@(#)misc.cc    1.24 21/09/06 2017-2021 J. Schilling";
   42 #endif
   43 
   44 /*
   45  *  misc.cc
   46  *
   47  *  This file contains various unclassified routines. Some main groups:
   48  *      getname
   49  *      Memory allocation
   50  *      String handling
   51  *      Property handling
   52  *      Error message handling
   53  *      Make internal state dumping
   54  *      main routine support
   55  */
   56 
   57 /*
   58  * Included files
   59  */
   60 #include <mk/defs.h>
   61 #include <mksh/macro.h>     /* SETVAR() */
   62 #include <mksh/misc.h>      /* enable_interrupt() */
   63 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
   64 #include <schily/stdarg.h>  /* va_list, va_start(), va_end() */
   65 #else
   66 #include <stdarg.h>     /* va_list, va_start(), va_end() */
   67 #endif
   68 #include <vroot/report.h>   /* SUNPRO_DEPENDENCIES */
   69 
   70 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
   71 #define MAXJOBS_ADJUST_RFE4694000
   72 
   73 #ifdef MAXJOBS_ADJUST_RFE4694000
   74 extern void job_adjust_fini();
   75 #endif /* MAXJOBS_ADJUST_RFE4694000 */
   76 #endif /* TEAMWARE_MAKE_CMN */
   77 
   78 /*
   79  * Defined macros
   80  */
   81 
   82 /*
   83  * typedefs & structs
   84  */
   85 
   86 /*
   87  * Static variables
   88  */
   89 
   90 /*
   91  * File table of contents
   92  */
   93 static  void        print_rule(register Name target);
   94 static  void        print_target_n_deps(register Name target);
   95 
   96 /*****************************************
   97  *
   98  *  getname
   99  */
  100 
  101 /*****************************************
  102  *
  103  *  Memory allocation
  104  */
  105 
  106 /*
  107  *  free_chain()
  108  *
  109  *  frees a chain of Name_vector's
  110  *
  111  *  Parameters:
  112  *      ptr     Pointer to the first element in the chain
  113  *              to be freed.
  114  *
  115  *  Global variables used:
  116  */
  117 void 
  118 free_chain(Name_vector ptr)
  119 {
  120     if (ptr != NULL) {
  121         if (ptr->next != NULL) {
  122             free_chain(ptr->next);
  123         }
  124         free((char *) ptr);
  125     }
  126 }
  127 
  128 /*****************************************
  129  *
  130  *  String manipulation
  131  */
  132 
  133 /*****************************************
  134  *
  135  *  Nameblock property handling
  136  */
  137 
  138 /*****************************************
  139  *
  140  *  Error message handling
  141  */
  142 
  143 /*
  144  *  fatal(format, args...)
  145  *
  146  *  Print a message and die
  147  *
  148  *  Parameters:
  149  *      format      printf type format string
  150  *      args        Arguments to match the format
  151  *
  152  *  Global variables used:
  153  *      fatal_in_progress Indicates if this is a recursive call
  154  *      parallel_process_cnt Do we need to wait for anything?
  155  *      report_pwd  Should we report the current path?
  156  */
  157 /*VARARGS*/
  158 void
  159 fatal(const char *message, ...)
  160 {
  161     va_list args;
  162 
  163     va_start(args, message);
  164     (void) fflush(stdout);
  165 #ifdef DISTRIBUTED
  166     (void) fprintf(stderr, gettext("dmake: Fatal error: "));
  167 #else
  168     (void) fprintf(stderr, gettext("make: Fatal error: "));
  169 #endif
  170     (void) vfprintf(stderr, message, args);
  171     (void) fprintf(stderr, "\n");
  172     va_end(args);
  173     if (report_pwd) {
  174         (void) fprintf(stderr,
  175                    gettext("Current working directory %s\n"),
  176                    get_current_path());
  177     }
  178     (void) fflush(stderr);
  179     if (fatal_in_progress) {
  180         exit_status = 1;
  181         exit(1);
  182     }
  183     fatal_in_progress = true;
  184 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
  185     /* Let all parallel children finish */
  186     if ((dmake_mode_type == parallel_mode) &&
  187         (parallel_process_cnt > 0)) {
  188         (void) fprintf(stderr,
  189                    gettext("Waiting for %d %s to finish\n"),
  190                    parallel_process_cnt,
  191                    parallel_process_cnt == 1 ?
  192                    gettext("job") : gettext("jobs"));
  193         (void) fflush(stderr);
  194     }
  195 
  196     while (parallel_process_cnt > 0) {
  197 #ifdef DISTRIBUTED
  198         if (dmake_mode_type == distributed_mode) {
  199             (void) await_dist(false);
  200         } else {
  201             await_parallel(true);
  202         }
  203 #else
  204         await_parallel(true);
  205 #endif
  206         finish_children(false);
  207     }
  208 #endif
  209 
  210 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && \
  211     defined(MAXJOBS_ADJUST_RFE4694000)
  212     job_adjust_fini();
  213 #endif
  214 
  215     exit_status = 1;
  216     exit(1);
  217 }
  218 
  219 /*
  220  *  warning(format, args...)
  221  *
  222  *  Print a message and continue.
  223  *
  224  *  Parameters:
  225  *      format      printf type format string
  226  *      args        Arguments to match the format
  227  *
  228  *  Global variables used:
  229  *      report_pwd  Should we report the current path?
  230  */
  231 /*VARARGS*/
  232 void
  233 warning(char * message, ...)
  234 {
  235     va_list args;
  236 
  237     va_start(args, message);
  238     (void) fflush(stdout);
  239 #ifdef DISTRIBUTED
  240     (void) fprintf(stderr, gettext("dmake: Warning: "));
  241 #else
  242     (void) fprintf(stderr, gettext("make: Warning: "));
  243 #endif
  244     (void) vfprintf(stderr, message, args);
  245     (void) fprintf(stderr, "\n");
  246     va_end(args);
  247     if (report_pwd) {
  248         (void) fprintf(stderr,
  249                    gettext("Current working directory %s\n"),
  250                    get_current_path());
  251     }
  252     (void) fflush(stderr);
  253 }
  254 
  255 /*
  256  *  time_to_string(time)
  257  *
  258  *  Take a numeric time value and produce
  259  *  a proper string representation.
  260  *
  261  *  Return value:
  262  *              The string representation of the time
  263  *
  264  *  Parameters:
  265  *      time        The time we need to translate
  266  *
  267  *  Global variables used:
  268  */
  269 char *
  270 time_to_string(const timestruc_t &time)
  271 {
  272     struct tm       *tm;
  273     char            buf[128];
  274 
  275         if (time == file_doesnt_exist) {
  276                 return gettext("File does not exist");
  277         }
  278         if (time == file_phony_time) {
  279                 return gettext("File is phony");
  280         }
  281         if (time == file_max_time) {
  282                 return gettext("Younger than any file");
  283         }
  284     tm = localtime(&time.tv_sec);
  285     strftime(buf, sizeof (buf), NOCATGETS("%c %Z"), tm);
  286         buf[127] = (int) nul_char;
  287         return strdup(buf);
  288 }
  289 
  290 /*
  291  *  get_current_path()
  292  *
  293  *  Stuff current_path with the current path if it isnt there already.
  294  *
  295  *  Parameters:
  296  *
  297  *  Global variables used:
  298  */
  299 char *
  300 get_current_path(void)
  301 {
  302     char            pwd[(MAXPATHLEN * MB_LEN_MAX)];
  303     static char     *current_path;
  304 
  305     if (current_path == NULL || current_path_reset == true) {
  306         Name        name;
  307         Name        value;
  308 
  309         pwd[0] = (int) nul_char;
  310 
  311         if (current_path != NULL)
  312             free(current_path);
  313         if (getcwd(pwd, sizeof(pwd)) == NULL ||
  314             pwd[0] == (int) nul_char) {
  315             pwd[0] = (int) slash_char;
  316             pwd[1] = (int) nul_char;
  317 #ifdef DISTRIBUTED
  318             current_path = strdup(pwd);
  319         } else if (IS_EQUALN(pwd, NOCATGETS("/tmp_mnt"), 8)) {
  320             current_path = strdup(pwd + 8);
  321         } else {
  322             current_path = strdup(pwd);
  323         }
  324 #else
  325         }
  326         current_path = strdup(pwd);
  327 #endif
  328         current_path_reset = false;
  329         MBSTOWCS(wcs_buffer, NOCATGETS("CURDIR"));
  330         name = GETNAME(wcs_buffer, FIND_LENGTH);
  331         MBSTOWCS(wcs_buffer, current_path);
  332         value = GETNAME(wcs_buffer, FIND_LENGTH);
  333         SETVAR(name, value, false); 
  334     }
  335     return current_path;
  336 }
  337 
  338 /*****************************************
  339  *
  340  *  Make internal state dumping
  341  *
  342  *  This is a set  of routines for dumping the internal make state
  343  *  Used for the -p option
  344  */
  345 
  346 /*
  347  *  dump_make_state()
  348  *
  349  *  Dump make's internal state to stdout
  350  *
  351  *  Parameters:
  352  *
  353  *  Global variables used:
  354  *      svr4            Was ".SVR4" seen in makefile?
  355  *      svr4_name       The Name ".SVR4", printed
  356  *      posix           Was ".POSIX" seen in makefile?
  357  *      posix_name      The Name ".POSIX", printed
  358  *      default_rule        Points to the .DEFAULT rule
  359  *      default_rule_name   The Name ".DEFAULT", printed
  360  *      default_target_to_build The first target to print
  361  *      dot_keep_state      The Name ".KEEP_STATE", printed
  362  *      dot_keep_state_file The Name ".KEEP_STATE_FILE", printed
  363  *      hashtab         The make hash table for Name blocks
  364  *      ignore_errors       Was ".IGNORE" seen in makefile?
  365  *      ignore_name     The Name ".IGNORE", printed
  366  *      keep_state      Was ".KEEP_STATE" seen in makefile?
  367  *      percent_list        The list of % rules
  368  *      phony           The Name ".PHONY", printed
  369  *      precious        The Name ".PRECIOUS", printed
  370  *      sccs_get_name       The Name ".SCCS_GET", printed
  371  *      sccs_get_posix_name The Name ".SCCS_GET_POSIX", printed
  372  *      get_name        The Name ".GET", printed
  373  *      get_posix_name      The Name ".GET_POSIX", printed
  374  *      sccs_get_rule       Points to the ".SCCS_GET" rule
  375  *      silent          Was ".SILENT" seen in makefile?
  376  *      silent_name     The Name ".SILENT", printed
  377  *      suffixes        The suffix list from ".SUFFIXES"
  378  *      suffixes_name       The Name ".SUFFIX", printed
  379  */
  380 void
  381 dump_make_state(void)
  382 {
  383     Name_set::iterator  p, e;
  384     register Property   prop;
  385     register Dependency dep;
  386     register Cmd_line   rule;
  387     Percent         percent, percent_depe;
  388 
  389     /* Default target */
  390     if (default_target_to_build != NULL) {
  391         print_rule(default_target_to_build);
  392     }
  393     (void) printf("\n");
  394 
  395     /* .POSIX */
  396     if (posix) {
  397         (void) printf("%s:\n", posix_name->string_mb);
  398     }
  399 
  400     /* .DEFAULT */
  401     if (default_rule != NULL) {
  402         (void) printf("%s:\n", default_rule_name->string_mb);
  403         for (rule = default_rule; rule != NULL; rule = rule->next) {
  404             (void) printf("\t%s\n", rule->command_line->string_mb);
  405         }
  406     }
  407 
  408     /* .IGNORE */
  409     if (ignore_errors) {
  410         (void) printf("%s:\n", ignore_name->string_mb);
  411     }
  412 
  413 #ifdef  DO_INCLUDE_FAILED
  414     /* .INCLUDE_FAILED */
  415     if (include_failed) {
  416         print_rule(include_failed_name);
  417     } else {
  418         include_failed_name->dependency_printed = true;
  419     }
  420 #endif
  421 
  422     /* .KEEP_STATE: */
  423     if (keep_state) {
  424         (void) printf("%s:\n\n", dot_keep_state->string_mb);
  425     }
  426 
  427     /* .PHONY */
  428     (void) printf("%s:", phony->string_mb);
  429     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  430             if (p->stat.is_phony) {
  431                 (void) printf(" %s", p->string_mb);
  432             }
  433     }
  434     (void) printf("\n");
  435 
  436     /* .PRECIOUS */
  437     (void) printf("%s:", precious->string_mb);
  438     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  439             if ((p->stat.is_precious) || (all_precious)) {
  440                 (void) printf(" %s", p->string_mb);
  441             }
  442     }
  443     (void) printf("\n");
  444 
  445     /* .SCCS_GET */
  446     if (sccs_get_rule != NULL) {
  447         (void) printf("%s:\n", sccs_get_name->string_mb);
  448         for (rule = sccs_get_rule; rule != NULL; rule = rule->next) {
  449             (void) printf("\t%s\n", rule->command_line->string_mb);
  450         }
  451     }
  452 
  453     /* .SILENT */
  454     if (silent) {
  455         (void) printf("%s:\n", silent_name->string_mb);
  456     }
  457 
  458     /* .SUFFIXES: */
  459     (void) printf("%s:", suffixes_name->string_mb);
  460     for (dep = suffixes; dep != NULL; dep = dep->next) {
  461         (void) printf(" %s", dep->name->string_mb);
  462         build_suffix_list(dep->name);
  463     }
  464     (void) printf("\n\n");
  465 
  466     /* % rules */
  467     for (percent = percent_list;
  468          percent != NULL;
  469          percent = percent->next) {
  470         (void) printf("%s:",
  471                   percent->name->string_mb);
  472         
  473         for (percent_depe = percent->dependencies;
  474              percent_depe != NULL;
  475              percent_depe = percent_depe->next) {
  476             (void) printf(" %s", percent_depe->name->string_mb);
  477         }
  478         
  479         (void) printf("\n");
  480 
  481         for (rule = percent->command_template;
  482              rule != NULL;
  483              rule = rule->next) {
  484             (void) printf("\t%s\n", rule->command_line->string_mb);
  485         }
  486     }
  487 
  488     /* Suffix rules */
  489     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  490             Wstring wcb(p);
  491             if (wcb.get_string()[0] == (int) period_char) {
  492                 print_rule(p);
  493             }
  494     }
  495 
  496     /* Macro assignments */
  497     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  498             if (((prop = get_prop(p->prop, macro_prop)) != NULL) &&
  499                 (prop->body.macro.value != NULL)) {
  500                 (void) printf("%s%s", p->string_mb,
  501                     p->stat.macro_type == gnu_assign ?
  502                     "::" : "");
  503                 print_value(prop->body.macro.value,
  504                         (Daemon) prop->body.macro.daemon);
  505             }
  506     }
  507     (void) printf("\n");
  508 
  509     /* Conditional macro assignments */
  510     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  511             for (prop = get_prop(p->prop, conditional_prop);
  512                  prop != NULL;
  513                  prop = get_prop(prop->next, conditional_prop)) {
  514                 (void) printf("%s := %s",
  515                           p->string_mb,
  516                           prop->body.conditional.name->
  517                           string_mb);
  518                 if (prop->body.conditional.append) {
  519                     printf(" +");
  520                 }
  521                 else {
  522                     printf(" ");
  523                 }
  524                 print_value(prop->body.conditional.value,
  525                         no_daemon);
  526             }
  527     }
  528     (void) printf("\n");
  529 
  530     /* All other dependencies */
  531     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  532             if (p->colons != no_colon) {
  533                 print_rule(p);
  534             }
  535     }
  536     (void) printf("\n");
  537 }
  538 
  539 /*
  540  *  print_rule(target)
  541  *
  542  *  Print the rule for one target
  543  *
  544  *  Parameters:
  545  *      target      Target we print rule for
  546  *
  547  *  Global variables used:
  548  */
  549 static void
  550 print_rule(register Name target)
  551 {
  552     register Cmd_line   rule;
  553     register Property   line;
  554     register Dependency dependency;
  555 
  556     if (target->dependency_printed ||
  557         ((line = get_prop(target->prop, line_prop)) == NULL) ||
  558         ((line->body.line.command_template == NULL) &&
  559          (line->body.line.dependencies == NULL))) {
  560         return;
  561     }
  562     target->dependency_printed = true;
  563 
  564     (void) printf("%s:", target->string_mb);
  565 
  566     for (dependency = line->body.line.dependencies;
  567          dependency != NULL;
  568          dependency = dependency->next) {
  569         (void) printf(" %s", dependency->name->string_mb);
  570     }
  571 
  572     (void) printf("\n");
  573 
  574     for (rule = line->body.line.command_template;
  575          rule != NULL;
  576          rule = rule->next) {
  577         (void) printf("\t%s\n", rule->command_line->string_mb);
  578     }
  579 }
  580 
  581 void
  582 dump_target_list(void)
  583 {
  584     Name_set::iterator  p, e;
  585     Wstring str;
  586 
  587     for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
  588             str.init(p);
  589             wchar_t * wcb = str.get_string();
  590             if ((p->colons != no_colon) &&
  591                 ((wcb[0] != (int) period_char) ||
  592                  ((wcb[0] == (int) period_char) &&
  593                   (wcschr(wcb, (int) slash_char))))) {
  594                 print_target_n_deps(p);
  595             }
  596     }
  597 }
  598 
  599 static void
  600 print_target_n_deps(register Name target)
  601 {
  602     register Cmd_line   rule;
  603     register Property   line;
  604     register Dependency dependency;
  605 
  606     if (target->dependency_printed) {
  607         return;
  608     }
  609     target->dependency_printed = true;
  610 
  611     (void) printf("%s\n", target->string_mb);
  612 
  613     if ((line = get_prop(target->prop, line_prop)) == NULL) {
  614         return;
  615     }
  616     for (dependency = line->body.line.dependencies;
  617          dependency != NULL;
  618          dependency = dependency->next) {
  619         if (!dependency->automatic) {
  620             print_target_n_deps(dependency->name);
  621         }
  622     }
  623 }
  624 
  625 /*****************************************
  626  *
  627  *  main() support
  628  */
  629 
  630 /*
  631  *  load_cached_names()
  632  *
  633  *  Load the vector of cached names
  634  *
  635  *  Parameters:
  636  *
  637  *  Global variables used:
  638  *      Many many pointers to Name blocks.
  639  */
  640 void
  641 load_cached_names(void)
  642 {
  643     char        *cp;
  644 
  645     /* Load the cached_names struct */
  646     MBSTOWCS(wcs_buffer, NOCATGETS(".BUILT_LAST_MAKE_RUN"));
  647     built_last_make_run = GETNAME(wcs_buffer, FIND_LENGTH);
  648     MBSTOWCS(wcs_buffer, NOCATGETS("@"));
  649     c_at = GETNAME(wcs_buffer, FIND_LENGTH);
  650     MBSTOWCS(wcs_buffer, NOCATGETS(" *conditionals* "));
  651     conditionals = GETNAME(wcs_buffer, FIND_LENGTH);
  652     /*
  653      * A version of make was released with NSE 1.0 that used
  654      * VERSION-1.1 but this version is identical to VERSION-1.0.
  655      * The version mismatch code makes a special case for this
  656      * situation.  If the version number is changed from 1.0
  657      * it should go to 1.2.
  658      */
  659     MBSTOWCS(wcs_buffer, NOCATGETS("VERSION-1.0"));
  660     current_make_version = GETNAME(wcs_buffer, FIND_LENGTH);
  661 #ifdef  DO_MAKE_NAME
  662     MBSTOWCS(wcs_buffer, NOCATGETS("MAKE_NAME"));
  663     sunpro_make_name = GETNAME(wcs_buffer, FIND_LENGTH);
  664 #endif
  665     MBSTOWCS(wcs_buffer, NOCATGETS(".SVR4"));
  666     svr4_name = GETNAME(wcs_buffer, FIND_LENGTH);
  667     MBSTOWCS(wcs_buffer, NOCATGETS(".POSIX"));
  668     posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
  669     MBSTOWCS(wcs_buffer, NOCATGETS(".DEFAULT"));
  670     default_rule_name = GETNAME(wcs_buffer, FIND_LENGTH);
  671 #ifdef NSE
  672     MBSTOWCS(wcs_buffer, NOCATGETS(".DERIVED_SRC"));
  673         derived_src= GETNAME(wcs_buffer, FIND_LENGTH);
  674 #endif
  675     MBSTOWCS(wcs_buffer, NOCATGETS("$"));
  676     dollar = GETNAME(wcs_buffer, FIND_LENGTH);
  677     MBSTOWCS(wcs_buffer, NOCATGETS(".DONE"));
  678     done = GETNAME(wcs_buffer, FIND_LENGTH);
  679     MBSTOWCS(wcs_buffer, NOCATGETS("."));
  680     dot = GETNAME(wcs_buffer, FIND_LENGTH);
  681     MBSTOWCS(wcs_buffer, NOCATGETS(".KEEP_STATE"));
  682     dot_keep_state = GETNAME(wcs_buffer, FIND_LENGTH);
  683     MBSTOWCS(wcs_buffer, NOCATGETS(".KEEP_STATE_FILE"));
  684     dot_keep_state_file = GETNAME(wcs_buffer, FIND_LENGTH);
  685     MBSTOWCS(wcs_buffer, NOCATGETS(""));
  686     empty_name = GETNAME(wcs_buffer, FIND_LENGTH);
  687     MBSTOWCS(wcs_buffer, NOCATGETS(" FORCE"));
  688     force = GETNAME(wcs_buffer, FIND_LENGTH);
  689     MBSTOWCS(wcs_buffer, NOCATGETS("HOST_ARCH"));
  690     host_arch = GETNAME(wcs_buffer, FIND_LENGTH);
  691     MBSTOWCS(wcs_buffer, NOCATGETS("HOST_MACH"));
  692     host_mach = GETNAME(wcs_buffer, FIND_LENGTH);
  693     MBSTOWCS(wcs_buffer, NOCATGETS(".IGNORE"));
  694     ignore_name = GETNAME(wcs_buffer, FIND_LENGTH);
  695 #ifdef  DO_INCLUDE_FAILED
  696     MBSTOWCS(wcs_buffer, NOCATGETS(".INCLUDE_FAILED"));
  697     include_failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
  698 #endif
  699     MBSTOWCS(wcs_buffer, NOCATGETS(".INIT"));
  700     init = GETNAME(wcs_buffer, FIND_LENGTH);
  701     MBSTOWCS(wcs_buffer, NOCATGETS(".LOCAL"));
  702     localhost_name = GETNAME(wcs_buffer, FIND_LENGTH);
  703     MBSTOWCS(wcs_buffer, NOCATGETS(".make.state"));
  704     make_state = GETNAME(wcs_buffer, FIND_LENGTH);
  705     MBSTOWCS(wcs_buffer, NOCATGETS("MAKEFLAGS"));
  706     makeflags = GETNAME(wcs_buffer, FIND_LENGTH);
  707     MBSTOWCS(wcs_buffer, NOCATGETS(".MAKE_VERSION"));
  708     make_version = GETNAME(wcs_buffer, FIND_LENGTH);
  709     MBSTOWCS(wcs_buffer, NOCATGETS(".NO_PARALLEL"));
  710     no_parallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
  711 #ifdef  DO_NOTPARALLEL
  712     MBSTOWCS(wcs_buffer, NOCATGETS(".NOTPARALLEL"));
  713     notparallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
  714 #endif
  715     MBSTOWCS(wcs_buffer, NOCATGETS(".NOT_AUTO"));
  716     not_auto = GETNAME(wcs_buffer, FIND_LENGTH);
  717     MBSTOWCS(wcs_buffer, NOCATGETS(".PARALLEL"));
  718     parallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
  719     MBSTOWCS(wcs_buffer, NOCATGETS("PATH"));
  720     path_name = GETNAME(wcs_buffer, FIND_LENGTH);
  721     MBSTOWCS(wcs_buffer, NOCATGETS("+"));
  722     plus = GETNAME(wcs_buffer, FIND_LENGTH);
  723     MBSTOWCS(wcs_buffer, NOCATGETS(".PHONY"));
  724     phony = GETNAME(wcs_buffer, FIND_LENGTH);
  725     MBSTOWCS(wcs_buffer, NOCATGETS(".PRECIOUS"));
  726     precious = GETNAME(wcs_buffer, FIND_LENGTH);
  727     MBSTOWCS(wcs_buffer, NOCATGETS("?"));
  728     query = GETNAME(wcs_buffer, FIND_LENGTH);
  729     MBSTOWCS(wcs_buffer, NOCATGETS("^"));
  730     hat = GETNAME(wcs_buffer, FIND_LENGTH);
  731     MBSTOWCS(wcs_buffer, NOCATGETS(".RECURSIVE"));
  732     recursive_name = GETNAME(wcs_buffer, FIND_LENGTH);
  733     MBSTOWCS(wcs_buffer, NOCATGETS(".SCCS_GET"));
  734     sccs_get_name = GETNAME(wcs_buffer, FIND_LENGTH);
  735     MBSTOWCS(wcs_buffer, NOCATGETS(".SCCS_GET_POSIX"));
  736     sccs_get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
  737     MBSTOWCS(wcs_buffer, NOCATGETS(".GET"));
  738     get_name = GETNAME(wcs_buffer, FIND_LENGTH);
  739     MBSTOWCS(wcs_buffer, NOCATGETS(".GET_POSIX"));
  740     get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
  741     MBSTOWCS(wcs_buffer, NOCATGETS("SHELL"));
  742     shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
  743     MBSTOWCS(wcs_buffer, NOCATGETS(".SILENT"));
  744     silent_name = GETNAME(wcs_buffer, FIND_LENGTH);
  745     MBSTOWCS(wcs_buffer, NOCATGETS(".SUFFIXES"));
  746     suffixes_name = GETNAME(wcs_buffer, FIND_LENGTH);
  747     MBSTOWCS(wcs_buffer, SUNPRO_DEPENDENCIES);
  748     sunpro_dependencies = GETNAME(wcs_buffer, FIND_LENGTH);
  749     MBSTOWCS(wcs_buffer, NOCATGETS("TARGET_ARCH"));
  750     target_arch = GETNAME(wcs_buffer, FIND_LENGTH);
  751     MBSTOWCS(wcs_buffer, NOCATGETS("TARGET_MACH"));
  752     target_mach = GETNAME(wcs_buffer, FIND_LENGTH);
  753     MBSTOWCS(wcs_buffer, NOCATGETS("VIRTUAL_ROOT"));
  754     virtual_root = GETNAME(wcs_buffer, FIND_LENGTH);
  755     MBSTOWCS(wcs_buffer, NOCATGETS("VPATH"));
  756     vpath_name = GETNAME(wcs_buffer, FIND_LENGTH);
  757     MBSTOWCS(wcs_buffer, NOCATGETS(".WAIT"));
  758     wait_name = GETNAME(wcs_buffer, FIND_LENGTH);
  759 
  760     wait_name->state = build_ok;
  761 
  762     /* Mark special targets so that the reader treats them properly */
  763     svr4_name->special_reader = svr4_special;
  764     posix_name->special_reader = posix_special;
  765     built_last_make_run->special_reader = built_last_make_run_special;
  766     default_rule_name->special_reader = default_special;
  767 #ifdef NSE
  768         derived_src->special_reader= derived_src_special;
  769 #endif
  770     dot_keep_state->special_reader = keep_state_special;
  771     dot_keep_state_file->special_reader = keep_state_file_special;
  772     ignore_name->special_reader = ignore_special;
  773 #ifdef  DO_INCLUDE_FAILED
  774     include_failed_name->special_reader = include_failed_special;
  775 #endif
  776     make_version->special_reader = make_version_special;
  777     no_parallel_name->special_reader = no_parallel_special;
  778 #ifdef  DO_NOTPARALLEL
  779     notparallel_name->special_reader = notparallel_special;
  780 #endif
  781     parallel_name->special_reader = parallel_special;
  782     localhost_name->special_reader = localhost_special;
  783     phony->special_reader = phony_special;
  784     precious->special_reader = precious_special;
  785     sccs_get_name->special_reader = sccs_get_special;
  786     sccs_get_posix_name->special_reader = sccs_get_posix_special;
  787     get_name->special_reader = get_special;
  788     get_posix_name->special_reader = get_posix_special;
  789     silent_name->special_reader = silent_special;
  790     suffixes_name->special_reader = suffixes_special;
  791 
  792     /* The value of $$ is $ */
  793     (void) SETVAR(dollar, dollar, false);
  794     dollar->dollar = false;
  795 
  796     /* Set the value of $(SHELL) */
  797     #if defined(SUN5_0)
  798     if (posix) {
  799 #ifdef  HAVE__USR_XPG4_BIN_SH
  800       MBSTOWCS(wcs_buffer, NOCATGETS("/usr/xpg4/bin/sh"));
  801 #else
  802 #ifdef  HAVE__OPT_SCHILY_XPG4_BIN_SH
  803       MBSTOWCS(wcs_buffer, NOCATGETS("/opt/schily/xpg4/bin/sh"));
  804 #else
  805 #ifdef  HAVE__BIN_POSIX_SH
  806       MBSTOWCS(wcs_buffer, NOCATGETS("/bin/posix/sh"));
  807 #else
  808       MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh"));
  809 #endif
  810 #endif
  811 #endif
  812     } else {
  813       MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh"));
  814     }
  815     #else  /* ^SUN5_0 */
  816     MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh"));
  817     #endif /* ^SUN5_0 */
  818     (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
  819 
  820     /*
  821      * Use " FORCE" to simulate a FRC dependency for :: type
  822      * targets with no dependencies.
  823      */
  824     (void) append_prop(force, line_prop);
  825     force->stat.time = file_max_time;
  826 
  827     /* Make sure VPATH is defined before current dir is read */
  828     if ((cp = getenv(vpath_name->string_mb)) != NULL) {
  829         MBSTOWCS(wcs_buffer, cp);
  830         (void) SETVAR(vpath_name,
  831                   GETNAME(wcs_buffer, FIND_LENGTH),
  832                   false);
  833     }
  834 
  835     /* Check if there is NO PATH variable. If not we construct one. */
  836     if (getenv(path_name->string_mb) == NULL) {
  837         vroot_path = NULL;
  838         add_dir_to_path(NOCATGETS("."), &vroot_path, -1);
  839         add_dir_to_path(NOCATGETS("/bin"), &vroot_path, -1);
  840         add_dir_to_path(NOCATGETS("/usr/bin"), &vroot_path, -1);
  841     }
  842 }
  843 
  844 /* 
  845  * iterate on list of conditional macros in np, and place them in 
  846  * a String_rec starting with, and separated by the '$' character.
  847  */
  848 void
  849 cond_macros_into_string(Name np, String_rec *buffer)
  850 {
  851     Macro_list  macro_list;
  852 
  853     /* 
  854      * Put the version number at the start of the string
  855      */
  856     MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION);
  857     append_string(wcs_buffer, buffer, FIND_LENGTH);
  858     /* 
  859      * Add the rest of the conditional macros to the buffer
  860      */
  861     if (np->depends_on_conditional){
  862         for (macro_list = np->conditional_macro_list; 
  863              macro_list != NULL; macro_list = macro_list->next){
  864             append_string(macro_list->macro_name, buffer, 
  865                 FIND_LENGTH);
  866             append_char((int) equal_char, buffer);
  867             append_string(macro_list->value, buffer, FIND_LENGTH);
  868             append_char((int) dollar_char, buffer);
  869         }
  870     }
  871 }
  872 /*
  873  *  Copyright (c) 1987-1992 Sun Microsystems, Inc.  All Rights Reserved.
  874  *  Sun considers its source code as an unpublished, proprietary
  875  *  trade secret, and it is available only under strict license
  876  *  provisions.  This copyright notice is placed here only to protect
  877  *  Sun in the event the source is deemed a published work.  Dissassembly,
  878  *  decompilation, or other means of reducing the object code to human
  879  *  readable form is prohibited by the license agreement under which
  880  *  this code is provided to the user or company in possession of this
  881  *  copy.
  882  *  RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
  883  *  Government is subject to restrictions as set forth in subparagraph
  884  *  (c)(1)(ii) of the Rights in Technical Data and Computer Software
  885  *  clause at DFARS 52.227-7013 and in similar clauses in the FAR and
  886  *  NASA FAR Supplement.
  887  *
  888  * 1.3 91/09/30
  889  */
  890 
  891 
  892 /* Some includes are commented because of the includes at the beginning */
  893 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
  894 /* #include <schily/signal.h> */
  895 #include <schily/types.h>
  896 #include <schily/stat.h>
  897 #include <schily/param.h>
  898 /* #include <schily/string.h> */
  899 #include <schily/unistd.h>
  900 #include <schily/stdlib.h>
  901 /* #include <schily/stdio.h> */
  902 #else
  903 /* #include <signal.h> */
  904 #include <sys/types.h>
  905 #include <sys/stat.h>
  906 #include <sys/param.h>
  907 /* #include <string.h> */
  908 #include <unistd.h>
  909 #include <stdlib.h>
  910 /* #include <stdio.h> */
  911 #endif  /* defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) */
  912 
  913 /* #include <avo/find_dir.h> */
  914 /* #ifndef TEAMWARE_MAKE_CMN
  915 #include <avo/find_dir.h>
  916 #endif TEAMWARE_MAKE_CMN */
  917 
  918 /* Routines to find the base directory name from which the various components
  919  * -executables, *crt* libraries etc will be accessed
  920  */
  921 
  922 /* This routine checks to see if a given filename is an executable or not.
  923    Logically similar to the csh statement : if  ( -x $i && ! -d $i )
  924  */
  925 
  926 static int
  927 check_if_exec(char *file)
  928 {
  929         struct stat stb;
  930         if (stat(file, &stb) < 0) {
  931                 return ( -1);
  932         }
  933         if (S_ISDIR(stb.st_mode)) {
  934                 return (-1);
  935         }
  936         if (!(stb.st_mode & S_IEXEC)) {
  937                 return ( -1);
  938         }
  939         return (0);
  940 }
  941 
  942 /* resolve - check for specified file in specified directory
  943  *  sets up dir, following symlinks.
  944  *  returns zero for success, or
  945  *  -1 for error (with errno set properly)
  946  */
  947 static int
  948 resolve (const char *indir, /* search directory */
  949      char   *cmd,       /* search for name */
  950      char   *dir,       /* directory buffer */
  951      char   **run)      /* resultion name ptr ptr */
  952 {
  953     char               *p;
  954     int                 rv = -1;
  955     int                 sll;
  956     char                symlink[MAXPATHLEN + 1];
  957 
  958     do {
  959     errno = ENAMETOOLONG;
  960     if ((strlen (indir) + strlen (cmd) + 2) > (size_t) MAXPATHLEN)
  961         break;
  962 
  963     sprintf(dir, "%s/%s", indir, cmd);
  964     if (check_if_exec(dir) != 0)  /* check if dir is an executable */
  965     {
  966         break;      /* Not an executable program */
  967     }
  968 
  969     /* follow symbolic links */
  970     while ((sll = readlink (dir, symlink, MAXPATHLEN)) >= 0) {
  971         symlink[sll] = 0;
  972         if (*symlink == '/')
  973         strcpy (dir, symlink);
  974         else
  975         sprintf (strrchr (dir, '/'), "/%s", symlink);
  976     }
  977     if (errno != EINVAL)
  978         break;
  979 
  980     p = strrchr (dir, '/');
  981     *p++ = 0;
  982     if (run)        /* user wants resolution name */
  983         *run = p;
  984     rv = 0;         /* complete, with success! */
  985 
  986     } while (0);
  987 
  988     return rv;
  989 }
  990 
  991 /* 
  992  *find_run_directory - find executable file in PATH
  993  *
  994  * PARAMETERS:
  995  *  cmd filename as typed by user (argv[0])
  996  *  cwd buffer from which is read the working directory
  997  *       if first character is '/' or into which is
  998  *       copied working directory name otherwise
  999  *  dir buffer into which is copied program's directory
 1000  *  pgm where to return pointer to tail of cmd (may be NULL
 1001  *       if not wanted) 
 1002  *  run where to return pointer to tail of final resolved
 1003  *       name ( dir/run is the program) (may be NULL
 1004  *       if not wanted)
 1005  *  path    user's path from environment
 1006  *
 1007  * Note: run and pgm will agree except when symbolic links have
 1008  *  renamed files
 1009  *
 1010  * RETURNS:
 1011  *  returns zero for success,
 1012  *  -1 for error (with errno set properly).
 1013  *
 1014  * EXAMPLE:
 1015  *  find_run_directory (argv[0], ".", &charray1, (char **) 0, (char **) 0,
 1016  *                          getenv(NOGETTEXT("PATH")));
 1017  */
 1018 extern int
 1019 find_run_directory (char    *cmd,
 1020             char    *cwd,
 1021             char    *dir,
 1022             char    **pgm,
 1023             char    **run,
 1024             char    *path)
 1025 {
 1026     int                 rv = 0;
 1027     char        *f, *s;
 1028     int         i;
 1029     char        tmp_path[MAXPATHLEN];
 1030 
 1031     if (!cmd || !*cmd || !cwd || !dir) {
 1032     errno = EINVAL;     /* stupid arguments! */
 1033     return -1;
 1034     }
 1035 
 1036     if (*cwd != '/')
 1037     if (!(getcwd (cwd, MAXPATHLEN)))
 1038         return -1;      /* can not get working directory */
 1039 
 1040     f = strrchr (cmd, '/');
 1041     if (pgm)            /* user wants program name */
 1042     *pgm = f ? f + 1 : cmd;
 1043 
 1044     /* get program directory */
 1045     rv = -1;
 1046     if (*cmd == '/')    /* absname given */
 1047     rv = resolve ("", cmd + 1, dir, run);
 1048     else if (f)     /* relname given */
 1049     rv = resolve (cwd, cmd, dir, run);
 1050     else {  /* from searchpath */
 1051         if (!path || !*path) {  /* if missing or null path */
 1052             tmp_path[0] = '.';  /* assume sanity */
 1053             tmp_path[1] = '\0';
 1054         } else {
 1055             strcpy(tmp_path, path);
 1056         }
 1057     f = tmp_path;
 1058     rv = -1;
 1059     errno = ENOENT; /* errno gets this if path empty */
 1060     while (*f && (rv < 0)) {
 1061         s = f;
 1062         while (*f && (*f != ':'))
 1063         ++f;
 1064         if (*f)
 1065         *f++ = 0;
 1066         if (*s == '/')
 1067         rv = resolve (s, cmd, dir, run);
 1068         else {
 1069         char                abuf[MAXPATHLEN];
 1070 
 1071         sprintf (abuf, "%s/%s", cwd, s);
 1072         rv = resolve (abuf, cmd, dir, run);
 1073         }
 1074     }
 1075     }
 1076 
 1077     /* Remove any trailing /. */
 1078     i = strlen(dir);
 1079     if ( dir[i-2] == '/' && dir[i-1] == '.') {
 1080         dir[i-2] = '\0';
 1081     }
 1082 
 1083     return rv;
 1084 }
 1085 
 1086 #ifdef  DO_ARCHCONF
 1087 /*
 1088  * Interface routines used by archconf.cc
 1089  */
 1090 void
 1091 define_var(const char *name, const char *value)
 1092 {
 1093     Name    thisname;
 1094 
 1095     MBSTOWCS(wcs_buffer, name);
 1096     thisname = GETNAME(wcs_buffer, FIND_LENGTH);
 1097 
 1098     MBSTOWCS(wcs_buffer, value);
 1099     SETVAR(thisname, GETNAME(wcs_buffer, FIND_LENGTH), false);
 1100 }
 1101 
 1102 char *
 1103 get_var(const char *name)
 1104 {
 1105     Name    thisname;
 1106     Name    thisvalue;
 1107 
 1108     MBSTOWCS(wcs_buffer, name);
 1109     thisname = getname_fn(wcs_buffer, FIND_LENGTH, true);
 1110     if (thisname == NULL)
 1111         return (NULL);
 1112     thisvalue = getvar(thisname);
 1113     if (thisvalue == NULL)
 1114         return (NULL);
 1115     return (thisvalue->string_mb);
 1116 }
 1117 #endif