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