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