1 #ifndef _MKSH_DEFS_H 2 #define _MKSH_DEFS_H 3 /* 4 * CDDL HEADER START 5 * 6 * This file and its contents are supplied under the terms of the 7 * Common Development and Distribution License ("CDDL"), version 1.0. 8 * You may use this file only in accordance with the terms of version 9 * 1.0 of the CDDL. 10 * 11 * A full copy of the text of the CDDL should have accompanied this 12 * source. A copy of the CDDL is also available via the Internet at 13 * http://www.opensource.org/licenses/cddl1.txt 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * 17 * When distributing Covered Code, include this CDDL HEADER in each 18 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 19 * If applicable, add the following below this CDDL HEADER, with the 20 * fields enclosed by brackets "[]" replaced with your own identifying 21 * information: Portions Copyright [yyyy] [name of copyright owner] 22 * 23 * CDDL HEADER END 24 */ 25 /* 26 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 /* 30 * @(#)defs.h 1.35 06/12/12 31 */ 32 33 #pragma ident "@(#)defs.h 1.35 06/12/12" 34 35 /* 36 * Copyright 2017-2021 J. Schilling 37 * 38 * @(#)defs.h 1.35 21/09/06 2017-2021 J. Schilling 39 */ 40 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 41 #include <schily/mconfig.h> 42 #ifndef HAVE_SEMAPHORE_H 43 #undef PMAKE 44 #endif 45 #ifdef NO_PMAKE 46 #undef PMAKE 47 #endif 48 #endif 49 50 /* 51 * This is not "#ifdef TEAMWARE_MAKE_CMN" because we're currently 52 * using the TW fake i18n headers and libraries to build both 53 * SMake and PMake on SPARC/S1 and x86/S2. 54 */ 55 56 #include <avo/intl.h> 57 58 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 59 #include <schily/limits.h> /* MB_LEN_MAX */ 60 #include <schily/stdio.h> 61 #include <schily/stdlib.h> /* wchar_t */ 62 #include <schily/unistd.h> /* close(), dup2() */ 63 #include <schily/string.h> /* strcmp() */ 64 #include <schily/nlsdefs.h> /* gettext() */ 65 #include <schily/param.h> /* MAXPATHLEN */ 66 #include <schily/types.h> /* time_t, caddr_t */ 67 #include <schily/fcntl.h> /* open() */ 68 #include <schily/time.h> /* timestruc_t */ 69 #include <schily/errno.h> /* errno */ 70 #include <schily/stat.h> /* stat_ansecs() */ 71 #include <schily/maxpath.h> /* MAXNAMELEN */ 72 #include <schily/getcwd.h> 73 /* 74 * Some Linux versions come with an incompatible prototype for bsd_signal() 75 */ 76 #define bsd_signal no_bsd_signal 77 #include <schily/signal.h> 78 #undef bsd_signal 79 #include <schily/dirent.h> /* opendir() */ 80 81 #if defined(HAVE__BIN_SH) && !defined(HAVE_SYMLINK__BIN) 82 #define SHELL_PATH NOCATGETS("/bin/sh") /* older UNIX */ 83 #else 84 #if defined(HAVE__USR_BIN_SH) 85 #define SHELL_PATH NOCATGETS("/usr/bin/sh") /* modern UNIX */ 86 #else 87 #define SHELL_PATH NOCATGETS("/bin/sh") /* last resort guess */ 88 #endif 89 #endif 90 91 #else /* defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) */ 92 #include <limits.h> /* MB_LEN_MAX */ 93 #include <stdio.h> 94 #include <stdlib.h> /* wchar_t */ 95 #include <unistd.h> 96 #include <string.h> /* strcmp() */ 97 #include <libintl.h> /* gettext() */ 98 #include <sys/param.h> /* MAXPATHLEN */ 99 #include <sys/types.h> /* time_t, caddr_t */ 100 #include <sys/fcntl.h> /* open() */ 101 #include <sys/time.h> /* timestruc_t */ 102 #include <errno.h> /* errno */ 103 #include <sys/stat.h> 104 #include <signal.h> 105 #if defined(SUN5_0) || defined(HP_UX) 106 #include <dirent.h> /* opendir() */ 107 #define SHELL_PATH NOCATGETS("/usr/bin/sh") 108 #else 109 #include <sys/dir.h> /* opendir() */ 110 #define SHELL_PATH NOCATGETS("/bin/sh") 111 #endif 112 #endif /* defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) */ 113 114 #include <vroot/vroot.h> /* pathpt */ 115 116 /* 117 * Definition of wchar functions. 118 */ 119 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 120 #include <schily/wctype.h> 121 #include <schily/wchar.h> 122 #include <schily/libport.h> 123 /* 124 * In order to support Ultrix, we need to supply missing prototypes that would 125 * otherwise terminate a C++ compilation. 126 */ 127 #ifdef ultrix 128 #ifdef __cplusplus 129 extern "C" { 130 #endif 131 extern long gethostid __PR((void)); 132 extern int strcasecmp __PR((const char *, const char *)); 133 134 extern int mkstemp __PR((char *)); 135 extern int putenv __PR((char *)); 136 extern int unsetenv __PR((char *)); 137 extern int symlink __PR((const char *, const char *)); 138 extern ssize_t readlink __PR((const char *, char *, size_t)); 139 140 extern int getopt __PR((int, char *const *, const char *)); 141 #ifdef IPC_CREAT 142 extern key_t ftok __PR((const char *, int)); 143 #endif 144 #ifdef __cplusplus 145 } 146 #endif 147 #endif /* ultrix */ 148 #else /* defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) */ 149 #ifdef HAVE_WCTYPE_H /* HP-UX-10.x does not have it */ 150 #include <wctype.h> 151 #endif 152 #include <wchar.h> 153 #endif /* defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) */ 154 155 /* 156 * A type and some utilities for boolean values 157 */ 158 159 #define false BOOLEAN_false 160 #define true BOOLEAN_true 161 162 typedef enum { 163 false = 0, 164 true = 1, 165 failed = 0, 166 succeeded = 1 167 } Boolean; 168 #define BOOLEAN(expr) ((expr) ? true : false) 169 170 /* 171 * Some random constants (in an enum so dbx knows their values) 172 */ 173 enum { 174 update_delay = 30, /* time between rstat checks */ 175 #ifdef sun386 176 ar_member_name_len = 14, 177 #else 178 #if defined(SUN5_0) || defined(linux) 179 ar_member_name_len = 1024, 180 #else 181 ar_member_name_len = 15, 182 #endif 183 #endif 184 185 hashsize = 2048 /* size of hash table */ 186 }; 187 188 189 /* 190 * Symbols that defines all the different char constants make uses 191 */ 192 enum { 193 ampersand_char = '&', 194 asterisk_char = '*', 195 at_char = '@', 196 backquote_char = '`', 197 backslash_char = '\\', 198 bar_char = '|', 199 braceleft_char = '{', 200 braceright_char = '}', 201 bracketleft_char = '[', 202 bracketright_char = ']', 203 colon_char = ':', 204 comma_char = ',', 205 dollar_char = '$', 206 doublequote_char = '"', 207 equal_char = '=', 208 exclam_char = '!', 209 greater_char = '>', 210 hat_char = '^', 211 hyphen_char = '-', 212 less_char = '<', 213 newline_char = '\n', 214 nul_char = '\0', 215 numbersign_char = '#', 216 parenleft_char = '(', 217 parenright_char = ')', 218 percent_char = '%', 219 period_char = '.', 220 plus_char = '+', 221 question_char = '?', 222 quote_char = '\'', 223 semicolon_char = ';', 224 slash_char = '/', 225 space_char = ' ', 226 tab_char = '\t', 227 tilde_char = '~' 228 }; 229 230 /* 231 * For make i18n. Codeset independent. 232 * Setup character semantics by identifying all the special characters 233 * of make, and assigning each an entry in the char_semantics[] vector. 234 */ 235 enum { 236 ampersand_char_entry = 0, /* 0 */ 237 asterisk_char_entry, /* 1 */ 238 at_char_entry, /* 2 */ 239 backquote_char_entry, /* 3 */ 240 backslash_char_entry, /* 4 */ 241 bar_char_entry, /* 5 */ 242 bracketleft_char_entry, /* 6 */ 243 bracketright_char_entry, /* 7 */ 244 colon_char_entry, /* 8 */ 245 dollar_char_entry, /* 9 */ 246 doublequote_char_entry, /* 10 */ 247 equal_char_entry, /* 11 */ 248 exclam_char_entry, /* 12 */ 249 greater_char_entry, /* 13 */ 250 hat_char_entry, /* 14 */ 251 hyphen_char_entry, /* 15 */ 252 less_char_entry, /* 16 */ 253 newline_char_entry, /* 17 */ 254 numbersign_char_entry, /* 18 */ 255 parenleft_char_entry, /* 19 */ 256 parenright_char_entry, /* 20 */ 257 percent_char_entry, /* 21 */ 258 plus_char_entry, /* 22 */ 259 question_char_entry, /* 23 */ 260 quote_char_entry, /* 24 */ 261 semicolon_char_entry, /* 25 */ 262 #ifdef SGE_SUPPORT 263 space_char_entry, /* 26 */ 264 tab_char_entry, /* 27 */ 265 no_semantics_entry /* 28 */ 266 #else 267 no_semantics_entry /* 26 */ 268 #endif /* SGE_SUPPORT */ 269 }; 270 271 /* 272 * CHAR_SEMANTICS_ENTRIES should be the number of entries above. 273 * The last entry in char_semantics[] should be blank. 274 */ 275 #ifdef SGE_SUPPORT 276 #define CHAR_SEMANTICS_ENTRIES 29 277 /* 278 #define CHAR_SEMANTICS_STRING "&*@`\\|[]:$=!>-\n#()%+?;^<'\" \t" 279 */ 280 #else 281 #define CHAR_SEMANTICS_ENTRIES 27 282 /* 283 #define CHAR_SEMANTICS_STRING "&*@`\\|[]:$=!>-\n#()%+?;^<'\"" 284 */ 285 #endif /* SGE_SUPPORT */ 286 287 /* 288 * Some utility macros 289 */ 290 #define ALLOC(x) ((struct _##x *)getmem(sizeof (struct _##x))) 291 #define ALLOC_WC(x) ((wchar_t *)getmem((x) * SIZEOFWCHAR_T)) 292 #define FIND_LENGTH -1 293 #define GETNAME(a,b) getname_fn((a), (b), false) 294 #define IS_EQUAL(a,b) (!strcmp((a), (b))) 295 #define IS_EQUALN(a,b,n) (!strncmp((a), (b), (n))) 296 #define IS_WEQUAL(a,b) (!wcscmp((a), (b))) 297 #define IS_WEQUALN(a,b,n) (!wcsncmp((a), (b), (n))) 298 #define MBLEN(a) mblen((a), MB_LEN_MAX) 299 #define MBSTOWCS(a,b) (void) mbstowcs_with_check((a), (b), MAXPATHLEN) 300 #define MBTOWC(a,b) mbtowc((a), (b), MB_LEN_MAX) 301 #define SIZEOFWCHAR_T (sizeof (wchar_t)) 302 #define VSIZEOF(v) (sizeof (v) / sizeof ((v)[0])) 303 #define WCSTOMBS(a,b) (void) wcstombs((a), (b), (MAXPATHLEN * MB_LEN_MAX)) 304 #define WCTOMB(a,b) (void) wctomb((a), (b)) 305 #define HASH(v, c) (v = (v)*31 + (unsigned int)(c)) 306 307 extern void mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n); 308 309 /* 310 * Bits stored in funny vector to classify chars 311 */ 312 enum { 313 dollar_sem = 0001, 314 meta_sem = 0002, 315 percent_sem = 0004, 316 wildcard_sem = 0010, 317 command_prefix_sem = 0020, 318 special_macro_sem = 0040, 319 colon_sem = 0100, 320 parenleft_sem = 0200 321 }; 322 323 /* 324 * Type returned from doname class functions 325 */ 326 typedef enum { 327 build_dont_know = 0, 328 build_failed, 329 build_ok, 330 build_in_progress, 331 build_running, /* PARALLEL & DISTRIBUTED */ 332 build_pending, /* PARALLEL & DISTRIBUTED */ 333 build_serial, /* PARALLEL & DISTRIBUTED */ 334 build_subtree /* PARALLEL & DISTRIBUTED */ 335 } Doname; 336 337 /* 338 * The String struct defines a string with the following layout 339 * "xxxxxxxxxxxxxxxCxxxxxxxxxxxxxxx________" 340 * ^ ^ ^ ^ 341 * | | | | 342 * buffer.start text.p text.end buffer.end 343 * text.p points to the next char to read/write. 344 */ 345 struct _String { 346 struct Text { 347 wchar_t *p; /* Read/Write pointer */ 348 wchar_t *end; /* Read limit pointer */ 349 } text; 350 struct Physical_buffer { 351 wchar_t *start; /* Points to start of buffer */ 352 wchar_t *end; /* End of physical buffer */ 353 } buffer; 354 Boolean free_after_use:1; 355 }; 356 357 #define STRING_BUFFER_LENGTH 1024 358 #define INIT_STRING_FROM_STACK(str, buf) { \ 359 str.buffer.start = (buf); \ 360 str.text.p = (buf); \ 361 str.text.end = NULL; \ 362 str.buffer.end = (buf) \ 363 + (sizeof (buf)/SIZEOFWCHAR_T); \ 364 str.free_after_use = false; \ 365 } 366 367 #define APPEND_NAME(np, dest, len) append_string((np)->string_mb, (dest), (len)); 368 369 class Wstring { 370 public: 371 struct _String string; 372 wchar_t string_buf[STRING_BUFFER_LENGTH]; 373 374 public: 375 Wstring(); 376 Wstring(struct _Name * name); 377 ~Wstring(); 378 379 void init(struct _Name * name); 380 void init(wchar_t * name, unsigned length); length()381 unsigned length() { 382 return wcslen(string.buffer.start); 383 }; 384 void append_to_str(struct _String * str, unsigned off, unsigned length); 385 get_string()386 wchar_t * get_string() { 387 return string.buffer.start; 388 }; 389 get_string(unsigned off)390 wchar_t * get_string(unsigned off) { 391 return string.buffer.start + off; 392 }; 393 394 Boolean equaln(wchar_t * str, unsigned length); 395 Boolean equal(wchar_t * str); 396 Boolean equal(wchar_t * str, unsigned off); 397 Boolean equal(wchar_t * str, unsigned off, unsigned length); 398 399 Boolean equaln(Wstring * str, unsigned length); 400 Boolean equal(Wstring * str); 401 Boolean equal(Wstring * str, unsigned off); 402 Boolean equal(Wstring * str, unsigned off, unsigned length); 403 }; 404 405 406 /* 407 * Used for storing the $? list and also for the "target + target:" 408 * construct. 409 */ 410 struct _Chain { 411 struct _Chain *next; 412 struct _Name *name; 413 struct _Percent *percent_member; 414 }; 415 416 /* 417 * Stores one command line for a rule 418 */ 419 struct _Cmd_line { 420 struct _Cmd_line *next; 421 struct _Name *command_line; 422 Boolean make_refd:1; /* $(MAKE) referenced? */ 423 /* 424 * Remember any command line prefixes given 425 */ 426 Boolean ignore_command_dependency:1; /* `?' */ 427 Boolean assign:1; /* `=' */ 428 Boolean ignore_error:1; /* `-' */ 429 Boolean silent:1; /* `@' */ 430 Boolean always_exec:1; /* `+' */ 431 }; 432 433 /* 434 * Linked list of targets/files 435 */ 436 struct _Dependency { 437 struct _Dependency *next; 438 struct _Name *name; 439 Boolean automatic:1; 440 Boolean stale:1; 441 Boolean built:1; 442 }; 443 444 /* 445 * The specials are markers for targets that the reader should special case 446 */ 447 typedef enum { 448 no_special, 449 built_last_make_run_special, 450 default_special, 451 #ifdef NSE 452 derived_src_special, 453 #endif 454 get_posix_special, 455 get_special, 456 ignore_special, 457 #ifdef DO_INCLUDE_FAILED 458 include_failed_special, 459 #endif 460 keep_state_file_special, 461 keep_state_special, 462 make_version_special, 463 no_parallel_special, 464 notparallel_special, 465 parallel_special, 466 posix_special, 467 phony_special, 468 precious_special, 469 sccs_get_posix_special, 470 sccs_get_special, 471 silent_special, 472 suffixes_special, 473 svr4_special, 474 localhost_special 475 } Special; 476 477 typedef enum { 478 no_colon, /* not used */ 479 one_colon, /* : seen */ 480 two_colon, /* :: seen */ 481 three_colon, /* ::: seen */ 482 equal_seen, /* = seen */ 483 conditional_seen, /* := seen */ 484 gnu_assign_seen, /* ::= seen */ 485 assign_seen, /* :::= seen */ 486 append_assign_seen, /* +:= seen */ 487 one_quest, /* ? seen */ 488 condequal_seen, /* ?= seen */ 489 none_seen 490 } Separator; 491 492 /* 493 * Magic values for the timestamp stored with each name object 494 */ 495 496 #if !defined(sun) || !defined(__SVR4) 497 /* 498 * timestruc_t is SVR4 specific 499 */ 500 #ifdef __nonono__ 501 /* 502 * We don't need this typedef, since there is a 503 * #define timestruc_t struct timespec 504 * in $(SRCROOT)/incs/ * /xconfig.h that is created by "configure" in 505 * case out current platform does not support that typedef. 506 */ 507 typedef struct timespec timestruc_t; 508 #endif 509 #endif 510 511 extern const timestruc_t file_no_time; 512 extern const timestruc_t file_doesnt_exist; 513 extern const timestruc_t file_is_dir; 514 extern const timestruc_t file_phony_time; 515 extern const timestruc_t file_min_time; 516 extern const timestruc_t file_max_time; 517 518 /* 519 * Each Name has a list of properties 520 * The properties are used to store information that only 521 * a subset of the Names need 522 */ 523 typedef enum { 524 no_prop, 525 conditional_prop, 526 line_prop, 527 macro_prop, 528 makefile_prop, 529 member_prop, 530 recursive_prop, 531 sccs_prop, 532 suffix_prop, 533 target_prop, 534 time_prop, 535 vpath_alias_prop, 536 long_member_name_prop, 537 macro_append_prop, 538 env_mem_prop 539 } Property_id; 540 541 typedef enum { 542 no_daemon = 0, 543 chain_daemon 544 } Daemon; 545 546 struct _Env_mem { 547 char *value; 548 }; 549 550 struct _Macro_appendix { 551 struct _Name *value; 552 struct _Name *value_to_append; 553 }; 554 555 struct _Macro { 556 /* 557 * For "ABC = xyz" constructs 558 * Name "ABC" get one macro prop 559 */ 560 struct _Name *value; 561 #ifdef NSE 562 Boolean imported:1; 563 #endif 564 Boolean exported:1; 565 Boolean read_only:1; 566 /* 567 * This macro is defined conditionally 568 */ 569 Boolean is_conditional:1; 570 /* 571 * The list for $? is stored as a structured list that 572 * is translated into a string iff it is referenced. 573 * This is why some macro values need a daemon. 574 */ 575 #if defined(HP_UX) || defined(linux) 576 Daemon daemon; 577 #else 578 Daemon daemon:2; 579 #endif 580 }; 581 582 struct _Macro_list { 583 struct _Macro_list *next; 584 char *macro_name; 585 char *value; 586 }; 587 588 enum sccs_stat { 589 DONT_KNOW_SCCS = 0, 590 NO_SCCS, 591 HAS_SCCS 592 }; 593 594 enum macro_type { 595 unknown_macro_type = 0, 596 normal_assign, 597 gnu_assign 598 }; 599 600 struct _Name { 601 struct _Property *prop; /* List of properties */ 602 char *string_mb; /* Multi-byte name string */ 603 struct { 604 unsigned int length; 605 } hash; 606 struct { 607 timestruc_t time; /* Modification */ 608 int stat_errno; /* error from "stat" */ 609 off_t size; /* Of file */ 610 mode_t mode; /* Of file */ 611 #if defined(HP_UX) || defined(linux) 612 Boolean is_file; 613 Boolean is_dir; 614 Boolean is_sym_link; 615 Boolean is_phony; 616 Boolean is_precious; 617 enum sccs_stat has_sccs; 618 enum macro_type macro_type; 619 #else 620 Boolean is_file:1; 621 Boolean is_dir:1; 622 Boolean is_sym_link:1; 623 Boolean is_phony:1; 624 Boolean is_precious:1; 625 #ifdef NSE 626 Boolean is_derived_src:1; 627 #endif 628 enum sccs_stat has_sccs:2; 629 enum macro_type macro_type:2; 630 #endif 631 } stat; 632 /* 633 * Count instances of :: definitions for this target 634 */ 635 short colon_splits; 636 /* 637 * We only clear the automatic depes once per target per report 638 */ 639 short temp_file_number; 640 /* 641 * Count how many conditional macros this target has defined 642 */ 643 short conditional_cnt; 644 /* 645 * A conditional macro was used when building this target 646 */ 647 Boolean depends_on_conditional:1; 648 /* 649 * Pointer to list of conditional macros which were used to build 650 * this target 651 */ 652 struct _Macro_list *conditional_macro_list; 653 Boolean has_member_depe:1; 654 Boolean is_member:1; 655 /* 656 * This target is a directory that has been read 657 */ 658 Boolean has_read_dir:1; 659 /* 660 * This name is a macro that is now being expanded 661 */ 662 Boolean being_expanded:1; 663 /* 664 * This name is a magic name that the reader must know about 665 */ 666 #if defined(HP_UX) || defined(linux) 667 Special special_reader; 668 Doname state; 669 Separator colons; 670 #else 671 Special special_reader:5; 672 Doname state:8; 673 Separator colons:8; 674 #endif 675 Boolean has_depe_list_expanded:1; 676 Boolean suffix_scan_done:1; 677 Boolean has_complained:1; /* For sccs */ 678 /* 679 * This target has been built during this make run 680 */ 681 Boolean ran_command:1; 682 Boolean with_squiggle:1; /* for .SUFFIXES */ 683 Boolean without_squiggle:1; /* for .SUFFIXES */ 684 Boolean has_read_suffixes:1; /* Suffix list cached*/ 685 Boolean has_suffixes:1; 686 Boolean has_target_prop:1; 687 Boolean has_vpath_alias_prop:1; 688 Boolean dependency_printed:1; /* For dump_make_state() */ 689 Boolean dollar:1; /* In namestring */ 690 Boolean meta:1; /* In namestring */ 691 Boolean percent:1; /* In namestring */ 692 Boolean wildcard:1; /* In namestring */ 693 Boolean has_parent:1; 694 Boolean is_target:1; 695 Boolean has_built:1; 696 Boolean colon:1; /* In namestring */ 697 Boolean parenleft:1; /* In namestring */ 698 Boolean has_recursive_dependency:1; 699 Boolean has_regular_dependency:1; 700 Boolean is_double_colon:1; 701 Boolean is_double_colon_parent:1; 702 Boolean has_long_member_name:1; 703 /* 704 * allowed to run in parallel 705 */ 706 Boolean parallel:1; 707 /* 708 * not allowed to run in parallel 709 */ 710 Boolean no_parallel:1; 711 /* 712 * used in dependency_conflict 713 */ 714 Boolean checking_subtree:1; 715 Boolean added_pattern_conditionals:1; 716 /* 717 * rechecking target for possible rebuild 718 */ 719 Boolean rechecking_target:1; 720 /* 721 * build this target in silent mode 722 */ 723 Boolean silent_mode:1; 724 /* 725 * build this target in ignore error mode 726 */ 727 Boolean ignore_error_mode:1; 728 Boolean dont_activate_cond_values:1; 729 /* 730 * allowed to run serially on local host 731 */ 732 Boolean localhost:1; 733 }; 734 735 /* 736 * Stores the % matched default rules 737 */ 738 struct _Percent { 739 struct _Percent *next; 740 struct _Name **patterns; 741 struct _Name *name; 742 struct _Percent *dependencies; 743 struct _Cmd_line *command_template; 744 struct _Chain *target_group; 745 int patterns_total; 746 Boolean being_expanded; 747 }; 748 749 struct Conditional { 750 /* 751 * For "foo := ABC [+]= xyz" constructs 752 * Name "foo" gets one conditional prop 753 */ 754 struct _Name *target; 755 struct _Name *name; 756 struct _Name *value; 757 int sequence; 758 Boolean append:1; 759 }; 760 761 struct Line { 762 /* 763 * For "target : dependencies" constructs 764 * Name "target" gets one line prop 765 */ 766 struct _Cmd_line *command_template; 767 struct _Cmd_line *command_used; 768 struct _Dependency *dependencies; 769 timestruc_t dependency_time; 770 struct _Chain *target_group; 771 Boolean is_out_of_date:1; 772 Boolean sccs_command:1; 773 Boolean command_template_redefined:1; 774 Boolean dont_rebuild_command_used:1; 775 /* 776 * Values for the dynamic macros 777 */ 778 struct _Name *target; 779 struct _Name *star; 780 struct _Name *less; 781 struct _Name *percent; 782 struct _Chain *query; 783 }; 784 785 struct Makefile { 786 /* 787 * Names that reference makefiles gets one prop 788 */ 789 wchar_t *contents; 790 off_t size; 791 }; 792 793 struct Member { 794 /* 795 * For "lib(member)" and "lib((entry))" constructs 796 * Name "lib(member)" gets one member prop 797 * Name "lib((entry))" gets one member prop 798 * The member field is filled in when the prop is refd 799 */ 800 struct _Name *library; 801 struct _Name *entry; 802 struct _Name *member; 803 }; 804 805 struct Recursive { 806 /* 807 * For "target: .RECURSIVE dir makefiles" constructs 808 * Used to keep track of recursive calls to make 809 * Name "target" gets one recursive prop 810 */ 811 struct _Name *directory; 812 struct _Name *target; 813 struct _Dependency *makefiles; 814 Boolean has_built; 815 Boolean in_depinfo; 816 }; 817 818 struct Sccs { 819 /* 820 * Each file that has a SCCS s. file gets one prop 821 */ 822 struct _Name *file; 823 }; 824 825 struct Suffix { 826 /* 827 * Cached list of suffixes that can build this target 828 * suffix is built from .SUFFIXES 829 */ 830 struct _Name *suffix; 831 struct _Cmd_line *command_template; 832 }; 833 834 struct Target { 835 /* 836 * For "target:: dependencies" constructs 837 * The "::" construct is handled by converting it to 838 * "foo: 1@foo" + "1@foo: dependecies" 839 * "1@foo" gets one target prop 840 * This target prop cause $@ to be bound to "foo" 841 * not "1@foo" when the rule is evaluated 842 */ 843 struct _Name *target; 844 }; 845 846 struct STime { 847 /* 848 * Save the original time for :: targets 849 */ 850 timestruc_t time; 851 }; 852 853 struct Vpath_alias { 854 /* 855 * If a file was found using the VPATH it gets 856 * a vpath_alias prop 857 */ 858 struct _Name *alias; 859 }; 860 861 struct Long_member_name { 862 /* 863 * Targets with a truncated member name carries 864 * the full lib(member) name for the state file 865 */ 866 struct _Name *member_name; 867 }; 868 869 union Body { 870 struct _Macro macro; 871 struct Conditional conditional; 872 struct Line line; 873 struct Makefile makefile; 874 struct Member member; 875 struct Recursive recursive; 876 struct Sccs sccs; 877 struct Suffix suffix; 878 struct Target target; 879 struct STime time; 880 struct Vpath_alias vpath_alias; 881 struct Long_member_name long_member_name; 882 struct _Macro_appendix macro_appendix; 883 struct _Env_mem env_mem; 884 }; 885 886 #define PROPERTY_HEAD_SIZE (sizeof (struct _Property)-sizeof (union Body)) 887 struct _Property { 888 struct _Property *next; 889 #if defined(HP_UX) || defined(linux) 890 Property_id type; 891 #else 892 Property_id type:4; 893 #endif 894 union Body body; 895 }; 896 897 /* Structure for dynamic "ascii" arrays */ 898 struct ASCII_Dyn_Array { 899 char *start; 900 size_t size; 901 }; 902 903 struct _Envvar { 904 struct _Name *name; 905 struct _Name *value; 906 struct _Envvar *next; 907 char *env_string; 908 Boolean already_put:1; 909 }; 910 911 /* 912 * Macros for the reader 913 */ 914 #define GOTO_STATE(new_state) { \ 915 SET_STATE(new_state); \ 916 goto enter_state; \ 917 } 918 #define SET_STATE(new_state) state = (new_state) 919 920 #define UNCACHE_SOURCE() if (source != NULL) { \ 921 source->string.text.p = source_p; \ 922 } 923 #define CACHE_SOURCE(comp) if (source != NULL) { \ 924 source_p = source->string.text.p - \ 925 (comp); \ 926 source_end = source->string.text.end; \ 927 } 928 #define GET_NEXT_BLOCK_NOCHK(source) { UNCACHE_SOURCE(); \ 929 source = get_next_block_fn(source); \ 930 CACHE_SOURCE(0) \ 931 } 932 #define GET_NEXT_BLOCK(source) { GET_NEXT_BLOCK_NOCHK(source); \ 933 if (source != NULL && source->error_converting) { \ 934 GOTO_STATE(illegal_bytes_state); \ 935 } \ 936 } 937 #define GET_CHAR() ((source == NULL) || \ 938 (source_p >= source_end) ? 0 : *source_p) 939 940 struct _Source { 941 struct _String string; 942 struct _Source *previous; 943 off_t bytes_left_in_file; 944 short fd; 945 Boolean already_expanded:1; 946 Boolean error_converting:1; 947 char *inp_buf; 948 char *inp_buf_end; 949 char *inp_buf_ptr; 950 }; 951 952 typedef enum { 953 reading_nothing, 954 reading_makefile, 955 reading_statefile, 956 rereading_statefile, 957 reading_cpp_file 958 } Makefile_type; 959 960 /* 961 * Typedefs for all structs 962 */ 963 typedef struct _Chain *Chain, Chain_rec; 964 typedef struct _Envvar *Envvar, Envvar_rec; 965 typedef struct _Macro_list *Macro_list, Macro_list_rec; 966 typedef struct _Name *Name, Name_rec; 967 typedef struct _Property *Property, Property_rec; 968 typedef struct _Source *Source, Source_rec; 969 typedef struct _String *String, String_rec; 970 971 /* 972 * name records hash table. 973 */ 974 struct Name_set { 975 private: 976 // single node in a tree 977 struct entry { entryName_set::entry978 entry(Name name_, entry *parent_) : 979 name(name_), 980 parent(parent_), 981 left(0), 982 right(0), 983 depth(1) 984 {} 985 986 Name name; 987 988 entry *parent; 989 entry *left; 990 entry *right; 991 unsigned depth; 992 setup_depthName_set::entry993 void setup_depth() { 994 unsigned rdepth = (right != 0) ? right->depth : 0; 995 unsigned ldepth = (left != 0) ? left->depth : 0; 996 depth = 1 + ((ldepth > rdepth) ? ldepth : rdepth); 997 } 998 }; 999 1000 public: 1001 // make iterator a friend of Name_set to have access to struct entry 1002 struct iterator; 1003 friend struct Name_set::iterator; 1004 1005 // iterator over tree nodes 1006 struct iterator { 1007 public: 1008 // constructors iteratorName_set::iterator1009 iterator() : node(0) {} iteratorName_set::iterator1010 iterator(entry *node_) : node(node_) {} 1011 1012 // dereference operator 1013 Name operator->() const { return node->name; } 1014 1015 // conversion operator NameName_set::iterator1016 operator Name() { return node->name; } 1017 1018 // assignment operator 1019 iterator& operator=(const iterator &o) { node = o.node; return *this; } 1020 1021 // equality/inequality operators 1022 int operator==(const iterator &o) const { return (node == o.node); } 1023 int operator!=(const iterator &o) const { return (node != o.node); } 1024 1025 // pre/post increment operators 1026 iterator& operator++(); 1027 iterator operator++(int) { iterator it = *this; ++*this; return it; } 1028 1029 private: 1030 // the node iterator points to 1031 entry *node; 1032 }; 1033 1034 public: 1035 // constructor Name_setName_set1036 Name_set() : root(0) {} 1037 1038 // lookup, insert and remove operations 1039 Name lookup(const char *key); 1040 Name insert(const char *key, Boolean &found); 1041 void insert(Name name); 1042 1043 // begin/end iterators 1044 iterator begin() const; endName_set1045 iterator end() const { return iterator(); } 1046 1047 private: 1048 // rebalance given node 1049 void rebalance(entry *node); 1050 1051 private: 1052 // tree root 1053 entry *root; 1054 }; 1055 1056 /* 1057 * extern declarations for all global variables. 1058 * The actual declarations are in globals.cc 1059 */ 1060 extern char char_semantics[]; 1061 extern wchar_t char_semantics_char[]; 1062 extern Macro_list cond_macro_list; 1063 extern Boolean conditional_macro_used; 1064 extern Boolean do_not_exec_rule; /* `-n' */ 1065 extern Boolean dollarget_seen; 1066 extern Boolean dollarless_flag; 1067 extern Name dollarless_value; 1068 extern "C" { 1069 extern char **environ; 1070 }; 1071 extern Envvar envvar; 1072 extern int exit_status; 1073 extern wchar_t *file_being_read; 1074 /* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */ 1075 extern Boolean gnu_style; 1076 extern Boolean sunpro_compat; 1077 extern Name_set hashtab; 1078 extern Name host_arch; 1079 extern Name host_mach; 1080 extern int line_number; 1081 extern char *make_state_lockfile; 1082 extern Boolean make_word_mentioned; 1083 extern Makefile_type makefile_type; 1084 extern char mbs_buffer[]; 1085 extern Name path_name; 1086 extern Boolean posix; 1087 extern Name query; 1088 extern Boolean query_mentioned; 1089 extern Name hat; 1090 extern Boolean reading_environment; 1091 extern Name shell_name; 1092 extern Boolean svr4; 1093 extern Name target_arch; 1094 extern Name target_mach; 1095 extern Boolean tilde_rule; 1096 extern wchar_t wcs_buffer[]; 1097 extern Boolean working_on_targets; 1098 extern Name virtual_root; 1099 extern Boolean vpath_defined; 1100 extern Name vpath_name; 1101 extern Boolean make_state_locked; 1102 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && defined(REDIRECT_ERR) 1103 extern Boolean out_err_same; 1104 #endif 1105 extern pid_t childPid; 1106 1107 /* 1108 * RFE 1257407: make does not use fine granularity time info available from stat. 1109 * High resolution time comparison. 1110 */ 1111 1112 inline int 1113 operator==(const timestruc_t &t1, const timestruc_t &t2) { 1114 return ((t1.tv_sec == t2.tv_sec) && (t1.tv_nsec == t2.tv_nsec)); 1115 } 1116 1117 inline int 1118 operator!=(const timestruc_t &t1, const timestruc_t &t2) { 1119 return ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec)); 1120 } 1121 1122 inline int 1123 operator>(const timestruc_t &t1, const timestruc_t &t2) { 1124 if (t1.tv_sec == t2.tv_sec) { 1125 return (t1.tv_nsec > t2.tv_nsec); 1126 } 1127 return (t1.tv_sec > t2.tv_sec); 1128 } 1129 1130 inline int 1131 operator>=(const timestruc_t &t1, const timestruc_t &t2) { 1132 if (t1.tv_sec == t2.tv_sec) { 1133 return (t1.tv_nsec >= t2.tv_nsec); 1134 } 1135 return (t1.tv_sec > t2.tv_sec); 1136 } 1137 1138 inline int 1139 operator<(const timestruc_t &t1, const timestruc_t &t2) { 1140 if (t1.tv_sec == t2.tv_sec) { 1141 return (t1.tv_nsec < t2.tv_nsec); 1142 } 1143 return (t1.tv_sec < t2.tv_sec); 1144 } 1145 1146 inline int 1147 operator<=(const timestruc_t &t1, const timestruc_t &t2) { 1148 if (t1.tv_sec == t2.tv_sec) { 1149 return (t1.tv_nsec <= t2.tv_nsec); 1150 } 1151 return (t1.tv_sec < t2.tv_sec); 1152 } 1153 1154 #endif 1155