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