"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.

    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