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