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