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