"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