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