root/usr/src/cmd/make/include/mksh/defs.h
#ifndef _MKSH_DEFS_H
#define _MKSH_DEFS_H
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
 * Use is subject to license terms.
 */

#include <limits.h>             /* MB_LEN_MAX */
#include <stdio.h>
#include <stdlib.h>             /* wchar_t */
#include <string.h>             /* strcmp() */
#include <sys/param.h>          /* MAXPATHLEN */
#include <sys/types.h>          /* time_t, caddr_t */
#include <vroot/vroot.h>        /* pathpt */
#include <sys/time.h>           /* timestruc_t */
#include <errno.h>              /* errno */

#include <wctype.h>

/*
 * A type and some utilities for boolean values
 */

#define false   BOOLEAN_false
#define true    BOOLEAN_true

typedef enum {
        false =         0,
        true =          1,
        failed =        0,
        succeeded =     1
} Boolean;
#define BOOLEAN(expr)           ((expr) ? true : false)

/*
 * Some random constants (in an enum so dbx knows their values)
 */
enum {
        update_delay = 30,              /* time between rstat checks */
        ar_member_name_len = 1024,
        hashsize = 2048                 /* size of hash table */
};


/*
 * Symbols that defines all the different char constants make uses
 */
enum {
        ampersand_char =        '&',
        asterisk_char =         '*',
        at_char =               '@',
        backquote_char =        '`',
        backslash_char =        '\\',
        bar_char =              '|',
        braceleft_char =        '{',
        braceright_char =       '}',
        bracketleft_char =      '[',
        bracketright_char =     ']',
        colon_char =            ':',
        comma_char =            ',',
        dollar_char =           '$',
        doublequote_char =      '"',
        equal_char =            '=',
        exclam_char =           '!',
        greater_char =          '>',
        hat_char =              '^',
        hyphen_char =           '-',
        less_char =             '<',
        newline_char =          '\n',
        nul_char =              '\0',
        numbersign_char =       '#',
        parenleft_char =        '(',
        parenright_char =       ')',
        percent_char =          '%',
        period_char =           '.',
        plus_char =             '+',
        question_char =         '?',
        quote_char =            '\'',
        semicolon_char =        ';',
        slash_char =            '/',
        space_char =            ' ',
        tab_char =              '\t',
        tilde_char =            '~'
};

/*
 * For make i18n. Codeset independent.
 * Setup character semantics by identifying all the special characters
 * of make, and assigning each an entry in the char_semantics[] vector.
 */
enum {
        ampersand_char_entry = 0,       /*  0 */
        asterisk_char_entry,            /*  1 */
        at_char_entry,                  /*  2 */
        backquote_char_entry,           /*  3 */
        backslash_char_entry,           /*  4 */
        bar_char_entry,                 /*  5 */
        bracketleft_char_entry,         /*  6 */
        bracketright_char_entry,        /*  7 */
        colon_char_entry,               /*  8 */
        dollar_char_entry,              /*  9 */
        doublequote_char_entry,         /* 10 */
        equal_char_entry,               /* 11 */
        exclam_char_entry,              /* 12 */
        greater_char_entry,             /* 13 */
        hat_char_entry,                 /* 14 */
        hyphen_char_entry,              /* 15 */
        less_char_entry,                /* 16 */
        newline_char_entry,             /* 17 */
        numbersign_char_entry,          /* 18 */
        parenleft_char_entry,           /* 19 */
        parenright_char_entry,          /* 20 */
        percent_char_entry,             /* 21 */
        plus_char_entry,                /* 22 */
        question_char_entry,            /* 23 */
        quote_char_entry,               /* 24 */
        semicolon_char_entry,           /* 25 */
        no_semantics_entry              /* 26 */
};

/*
 * CHAR_SEMANTICS_ENTRIES should be the number of entries above.
 * The last entry in char_semantics[] should be blank.
 */
#define CHAR_SEMANTICS_ENTRIES  27
/*
#define CHAR_SEMANTICS_STRING   "&*@`\\|[]:$=!>-\n#()%+?;^<'\""
 */

/*
 * Some utility macros
 */
#define ALLOC(x)                ((struct _##x *)getmem(sizeof (struct _##x)))
#define ALLOC_WC(x)             ((wchar_t *)getmem((x) * SIZEOFWCHAR_T))
#define FIND_LENGTH             -1
#define GETNAME(a,b)            getname_fn((a), (b), false)
#define IS_EQUAL(a,b)           (!strcmp((a), (b)))
#define IS_EQUALN(a,b,n)        (!strncmp((a), (b), (n)))
#define IS_WEQUAL(a,b)          (!wcscmp((a), (b)))
#define IS_WEQUALN(a,b,n)       (!wcsncmp((a), (b), (n)))
#define MBLEN(a)                mblen((a), MB_LEN_MAX)
#define MBSTOWCS(a,b)           (void) mbstowcs_with_check((a), (b), MAXPATHLEN)
#define MBTOWC(a,b)             mbtowc((a), (b), MB_LEN_MAX)
#define SIZEOFWCHAR_T           (sizeof (wchar_t))
#define VSIZEOF(v)              (sizeof (v) / sizeof ((v)[0]))
#define WCSTOMBS(a,b)           (void) wcstombs((a), (b), (MAXPATHLEN * MB_LEN_MAX))
#define WCTOMB(a,b)             (void) wctomb((a), (b))
#define HASH(v, c)              (v = (v)*31 + (unsigned int)(c))

extern void mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n);

/*
 * Bits stored in funny vector to classify chars
 */
enum {
        dollar_sem =            0001,
        meta_sem =              0002,
        percent_sem =           0004,
        wildcard_sem =          0010,
        command_prefix_sem =    0020,
        special_macro_sem =     0040,
        colon_sem =             0100,
        parenleft_sem =         0200
};

/*
 * Type returned from doname class functions
 */
typedef enum {
        build_dont_know = 0,
        build_failed,
        build_ok,
        build_in_progress,
        build_running,          /* PARALLEL & DISTRIBUTED */
        build_pending,          /* PARALLEL & DISTRIBUTED */
        build_serial,           /* PARALLEL & DISTRIBUTED */
        build_subtree           /* PARALLEL & DISTRIBUTED */
} Doname;

/*
 * The String struct defines a string with the following layout
 *      "xxxxxxxxxxxxxxxCxxxxxxxxxxxxxxx________"
 *      ^               ^               ^               ^
 *      |               |               |               |
 *      buffer.start    text.p          text.end        buffer.end
 *      text.p points to the next char to read/write.
 */
struct _String {
        struct Text {
                wchar_t         *p;     /* Read/Write pointer */
                wchar_t         *end;   /* Read limit pointer */
        }               text;
        struct Physical_buffer {
                wchar_t         *start; /* Points to start of buffer */
                wchar_t         *end;   /* End of physical buffer */
        }               buffer;
        Boolean         free_after_use:1;
};

#define STRING_BUFFER_LENGTH    1024
#define INIT_STRING_FROM_STACK(str, buf) { \
                        str.buffer.start = (buf); \
                        str.text.p = (buf); \
                        str.text.end = NULL; \
                        str.buffer.end = (buf) \
                          + (sizeof (buf)/SIZEOFWCHAR_T); \
                        str.free_after_use = false; \
                  }

#define APPEND_NAME(np, dest, len)      append_string((np)->string_mb, (dest), (len));

class Wstring {
        public:
                struct _String  string;
                wchar_t         string_buf[STRING_BUFFER_LENGTH];

        public:
                Wstring();
                Wstring(struct _Name * name);
                ~Wstring();

                void init(struct _Name * name);
                void init(wchar_t * name, unsigned length);
                unsigned length() {
                        return wcslen(string.buffer.start);
                };
                void append_to_str(struct _String * str, unsigned off, unsigned length);

                wchar_t * get_string() {
                        return string.buffer.start;
                };

                wchar_t * get_string(unsigned off) {
                        return string.buffer.start + off;
                };

                Boolean equaln(wchar_t * str, unsigned length);
                Boolean equal(wchar_t * str);
                Boolean equal(wchar_t * str, unsigned off);
                Boolean equal(wchar_t * str, unsigned off, unsigned length);

                Boolean equaln(Wstring * str, unsigned length);
                Boolean equal(Wstring * str);
                Boolean equal(Wstring * str, unsigned off);
                Boolean equal(Wstring * str, unsigned off, unsigned length);
};


/*
 * Used for storing the $? list and also for the "target + target:"
 * construct.
 */
struct _Chain {
        struct _Chain           *next;
        struct _Name            *name;
        struct _Percent *percent_member;
};

/*
 * Stores one command line for a rule
 */
struct _Cmd_line {
        struct _Cmd_line        *next;
        struct _Name            *command_line;
        Boolean                 make_refd:1;    /* $(MAKE) referenced? */
        /*
         * Remember any command line prefixes given
         */
        Boolean                 ignore_command_dependency:1;    /* `?' */
        Boolean                 assign:1;                       /* `=' */
        Boolean                 ignore_error:1;                 /* `-' */
        Boolean                 silent:1;                       /* `@' */
        Boolean                 always_exec:1;                  /* `+' */
};

/*
 * Linked list of targets/files
 */
struct _Dependency {
        struct _Dependency      *next;
        struct _Name            *name;
        Boolean                 automatic:1;
        Boolean                 stale:1;
        Boolean                 built:1;
};

/*
 * The specials are markers for targets that the reader should special case
 */
typedef enum {
        no_special,
        built_last_make_run_special,
        default_special,
        get_posix_special,
        get_special,
        ignore_special,
        keep_state_file_special,
        keep_state_special,
        make_version_special,
        no_parallel_special,
        parallel_special,
        posix_special,
        precious_special,
        sccs_get_posix_special,
        sccs_get_special,
        silent_special,
        suffixes_special,
        svr4_special,
        localhost_special
} Special;

typedef enum {
        no_colon,
        one_colon,
        two_colon,
        equal_seen,
        conditional_seen,
        none_seen
} Separator;

/*
 * Magic values for the timestamp stored with each name object
 */


extern const timestruc_t file_no_time;
extern const timestruc_t file_doesnt_exist;
extern const timestruc_t file_is_dir;
extern const timestruc_t file_min_time;
extern const timestruc_t file_max_time;

/*
 * Each Name has a list of properties
 * The properties are used to store information that only
 * a subset of the Names need
 */
typedef enum {
        no_prop,
        conditional_prop,
        line_prop,
        macro_prop,
        makefile_prop,
        member_prop,
        recursive_prop,
        sccs_prop,
        suffix_prop,
        target_prop,
        time_prop,
        vpath_alias_prop,
        long_member_name_prop,
        macro_append_prop,
        env_mem_prop
} Property_id;

typedef enum {
        no_daemon = 0,
        chain_daemon
} Daemon;

struct _Env_mem {
        char            *value;
};

struct _Macro_appendix {
        struct _Name            *value;
        struct _Name            *value_to_append;
};

struct _Macro {
        /*
        * For "ABC = xyz" constructs
        * Name "ABC" get one macro prop
        */
        struct _Name            *value;
        Boolean                 exported:1;
        Boolean                 read_only:1;
        /*
        * This macro is defined conditionally
        */
        Boolean                 is_conditional:1;
        /*
        * The list for $? is stored as a structured list that
        * is translated into a string iff it is referenced.
        * This is why  some macro values need a daemon.
        */
        Daemon                  daemon:2;
};

struct _Macro_list {
        struct _Macro_list      *next;
        char                    *macro_name;
        char                    *value;
};

enum sccs_stat {
        DONT_KNOW_SCCS = 0,
        NO_SCCS,
        HAS_SCCS
};

struct _Name {
        struct _Property        *prop;          /* List of properties */
        char                    *string_mb;     /* Multi-byte name string */
        struct {
                unsigned int            length;
        }                       hash;
        struct {
                timestruc_t             time;           /* Modification */
                int                     stat_errno;     /* error from "stat" */
                off_t                   size;           /* Of file */
                mode_t                  mode;           /* Of file */
                Boolean                 is_file:1;
                Boolean                 is_dir:1;
                Boolean                 is_sym_link:1;
                Boolean                 is_precious:1;
                enum sccs_stat          has_sccs:2;
        }                       stat;
        /*
         * Count instances of :: definitions for this target
         */
        short                   colon_splits;
        /*
         * We only clear the automatic depes once per target per report
         */
        short                   temp_file_number;
        /*
         * Count how many conditional macros this target has defined
         */
        short                   conditional_cnt;
        /*
         * A conditional macro was used when building this target
         */
        Boolean                 depends_on_conditional:1;
        /*
         * Pointer to list of conditional macros which were used to build
         * this target
         */
        struct _Macro_list      *conditional_macro_list;
        Boolean                 has_member_depe:1;
        Boolean                 is_member:1;
        /*
         * This target is a directory that has been read
         */
        Boolean                 has_read_dir:1;
        /*
         * This name is a macro that is now being expanded
         */
        Boolean                 being_expanded:1;
        /*
         * This name is a magic name that the reader must know about
         */
        Special                 special_reader:5;
        Doname                  state:3;
        Separator               colons:3;
        Boolean                 has_depe_list_expanded:1;
        Boolean                 suffix_scan_done:1;
        Boolean                 has_complained:1;       /* For sccs */
        /*
         * This target has been built during this make run
         */
        Boolean                 ran_command:1;
        Boolean                 with_squiggle:1;        /* for .SUFFIXES */
        Boolean                 without_squiggle:1;     /* for .SUFFIXES */
        Boolean                 has_read_suffixes:1;    /* Suffix list cached*/
        Boolean                 has_suffixes:1;
        Boolean                 has_target_prop:1;
        Boolean                 has_vpath_alias_prop:1;
        Boolean                 dependency_printed:1;   /* For dump_make_state() */
        Boolean                 dollar:1;               /* In namestring */
        Boolean                 meta:1;                 /* In namestring */
        Boolean                 percent:1;              /* In namestring */
        Boolean                 wildcard:1;             /* In namestring */
        Boolean                 has_parent:1;
        Boolean                 is_target:1;
        Boolean                 has_built:1;
        Boolean                 colon:1;                /* In namestring */
        Boolean                 parenleft:1;            /* In namestring */
        Boolean                 has_recursive_dependency:1;
        Boolean                 has_regular_dependency:1;
        Boolean                 is_double_colon:1;
        Boolean                 is_double_colon_parent:1;
        Boolean                 has_long_member_name:1;
        /*
         * allowed to run in parallel
         */
        Boolean                 parallel:1;
        /*
         * not allowed to run in parallel
         */
        Boolean                 no_parallel:1;
        /*
         * used in dependency_conflict
         */
        Boolean                 checking_subtree:1;
        Boolean                 added_pattern_conditionals:1;
        /*
         * rechecking target for possible rebuild
         */
        Boolean                 rechecking_target:1;
        /*
         * build this target in silent mode
         */
        Boolean                 silent_mode:1;
        /*
         * build this target in ignore error mode
         */
        Boolean                 ignore_error_mode:1;
        Boolean                 dont_activate_cond_values:1;
        /*
         * allowed to run serially on local host
         */
        Boolean                 localhost:1;
};

/*
 * Stores the % matched default rules
 */
struct _Percent {
        struct _Percent *next;
        struct _Name            **patterns;
        struct _Name            *name;
        struct _Percent         *dependencies;
        struct _Cmd_line        *command_template;
        struct _Chain           *target_group;
        int                     patterns_total;
        Boolean                 being_expanded;
};

struct Conditional {
        /*
         * For "foo := ABC [+]= xyz" constructs
         * Name "foo" gets one conditional prop
         */
        struct _Name            *target;
        struct _Name            *name;
        struct _Name            *value;
        int                     sequence;
        Boolean                 append:1;
};

struct Line {
        /*
         * For "target : dependencies" constructs
         * Name "target" gets one line prop
         */
        struct _Cmd_line        *command_template;
        struct _Cmd_line        *command_used;
        struct _Dependency      *dependencies;
        timestruc_t             dependency_time;
        struct _Chain           *target_group;
        Boolean                 is_out_of_date:1;
        Boolean                 sccs_command:1;
        Boolean                 command_template_redefined:1;
        Boolean                 dont_rebuild_command_used:1;
        /*
         * Values for the dynamic macros
         */
        struct _Name            *target;
        struct _Name            *star;
        struct _Name            *less;
        struct _Name            *percent;
        struct _Chain           *query;
};

struct Makefile {
        /*
         * Names that reference makefiles gets one prop
         */
        wchar_t                 *contents;
        off_t                   size;
};

struct Member {
        /*
         * For "lib(member)" and "lib((entry))" constructs
         * Name "lib(member)" gets one member prop
         * Name "lib((entry))" gets one member prop
         * The member field is filled in when the prop is refd
         */
        struct _Name            *library;
        struct _Name            *entry;
        struct _Name            *member;
};

struct Recursive {
        /*
         * For "target: .RECURSIVE dir makefiles" constructs
         * Used to keep track of recursive calls to make
         * Name "target" gets one recursive prop
         */
        struct _Name            *directory;
        struct _Name            *target;
        struct _Dependency      *makefiles;
        Boolean                 has_built;
        Boolean                 in_depinfo;
};

struct Sccs {
        /*
         * Each file that has a SCCS s. file gets one prop
         */
        struct _Name            *file;
};

struct Suffix {
        /*
         * Cached list of suffixes that can build this target
         * suffix is built from .SUFFIXES
         */
        struct _Name            *suffix;
        struct _Cmd_line        *command_template;
};

struct Target {
        /*
         * For "target:: dependencies" constructs
         * The "::" construct is handled by converting it to
         * "foo: 1@foo" + "1@foo: dependecies"
         * "1@foo" gets one target prop
         * This target prop cause $@ to be bound to "foo"
         * not "1@foo" when the rule is evaluated
         */
        struct _Name            *target;
};

struct STime {
        /*
         * Save the original time for :: targets
         */
        timestruc_t                     time;
};

struct Vpath_alias {
        /*
         * If a file was found using the VPATH it gets
         * a vpath_alias prop
         */
        struct _Name            *alias;
};

struct Long_member_name {
        /*
         * Targets with a truncated member name carries
         * the full lib(member) name for the state file
         */
        struct _Name            *member_name;
};

union Body {
        struct _Macro           macro;
        struct Conditional      conditional;
        struct Line             line;
        struct Makefile         makefile;
        struct Member           member;
        struct Recursive        recursive;
        struct Sccs             sccs;
        struct Suffix           suffix;
        struct Target           target;
        struct STime            time;
        struct Vpath_alias      vpath_alias;
        struct Long_member_name long_member_name;
        struct _Macro_appendix  macro_appendix;
        struct _Env_mem         env_mem;
};

#define PROPERTY_HEAD_SIZE (sizeof (struct _Property)-sizeof (union Body))
struct _Property {
        struct _Property        *next;
        Property_id             type:4;
        union Body              body;
};

/* Structure for dynamic "ascii" arrays */
struct ASCII_Dyn_Array {
        char                    *start;
        size_t                  size;
};

struct _Envvar {
        struct _Name            *name;
        struct _Name            *value;
        struct _Envvar          *next;
        char                    *env_string;
        Boolean                 already_put:1;
};

/*
 * Macros for the reader
 */
#define GOTO_STATE(new_state) { \
                                  SET_STATE(new_state); \
                                    goto enter_state; \
                              }
#define SET_STATE(new_state) state = (new_state)

#define UNCACHE_SOURCE()        if (source != NULL) { \
                                        source->string.text.p = source_p; \
                                  }
#define CACHE_SOURCE(comp)      if (source != NULL) { \
                                        source_p = source->string.text.p - \
                                          (comp); \
                                        source_end = source->string.text.end; \
                                  }
#define GET_NEXT_BLOCK_NOCHK(source)    { UNCACHE_SOURCE(); \
                                 source = get_next_block_fn(source); \
                                 CACHE_SOURCE(0) \
                           }
#define GET_NEXT_BLOCK(source)  { GET_NEXT_BLOCK_NOCHK(source); \
                                 if (source != NULL && source->error_converting) { \
                                        GOTO_STATE(illegal_bytes_state); \
                                 } \
                           }
#define GET_CHAR()              ((source == NULL) || \
                                (source_p >= source_end) ? 0 : *source_p)

struct _Source {
        struct _String          string;
        struct _Source          *previous;
        off_t                   bytes_left_in_file;
        short                   fd;
        Boolean                 already_expanded:1;
        Boolean                 error_converting:1;
        char                    *inp_buf;
        char                    *inp_buf_end;
        char                    *inp_buf_ptr;
};

typedef enum {
        reading_nothing,
        reading_makefile,
        reading_statefile,
        rereading_statefile,
        reading_cpp_file
} Makefile_type;

/*
 * Typedefs for all structs
 */
typedef struct _Chain           *Chain, Chain_rec;
typedef struct _Envvar          *Envvar, Envvar_rec;
typedef struct _Macro_list      *Macro_list, Macro_list_rec;
typedef struct _Name            *Name, Name_rec;
typedef struct _Property        *Property, Property_rec;
typedef struct _Source          *Source, Source_rec;
typedef struct _String          *String, String_rec;

/*
 * name records hash table.
 */
struct Name_set {
private:
        // single node in a tree
        struct entry {
                entry(Name name_, entry *parent_) :
                        name(name_),
                        parent(parent_),
                        left(0),
                        right(0),
                        depth(1)
                {}

                Name            name;

                entry           *parent;
                entry           *left;
                entry           *right;
                unsigned        depth;

                void setup_depth() {
                        unsigned rdepth = (right != 0) ? right->depth : 0;
                        unsigned ldepth = (left != 0) ? left->depth : 0;
                        depth = 1 + ((ldepth > rdepth) ? ldepth : rdepth);
                }
        };

public:
        // make iterator a friend of Name_set to have access to struct entry
        struct iterator;
        friend struct Name_set::iterator;

        // iterator over tree nodes
        struct iterator {
        public:
                // constructors
                iterator() : node(0) {}
                iterator(entry *node_) : node(node_) {}
                iterator(const iterator&) = default;

                // dereference operator
                Name operator->() const { return node->name; }

                // conversion operator
                operator Name() { return node->name; }

                // assignment operator
                iterator& operator=(const iterator &o) { node = o.node; return *this; }

                // equality/inequality operators
                int operator==(const iterator &o) const { return (node == o.node); }
                int operator!=(const iterator &o) const { return (node != o.node); }

                // pre/post increment operators
                iterator& operator++();
                iterator  operator++(int) { iterator it = *this; ++*this; return it; }

        private:
                // the node iterator points to
                entry *node;
        };

public:
        // constructor
        Name_set() : root(0) {}

        // lookup, insert and remove operations
        Name lookup(const char *key);
        Name insert(const char *key, Boolean &found);
        void insert(Name name);

        // begin/end iterators
        iterator begin() const;
        iterator end() const { return iterator(); }

private:
        // rebalance given node
        void    rebalance(entry *node);

private:
        // tree root
        entry   *root;
};

/*
 *      extern declarations for all global variables.
 *      The actual declarations are in globals.cc
 */
extern char             char_semantics[];
extern wchar_t          char_semantics_char[];
extern Macro_list       cond_macro_list;
extern Boolean          conditional_macro_used;
extern Boolean          do_not_exec_rule;               /* `-n' */
extern Boolean          dollarget_seen;
extern Boolean          dollarless_flag;
extern Name             dollarless_value;
extern char             **environ;
extern Envvar           envvar;
extern int              exit_status;
extern wchar_t          *file_being_read;
/* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */
extern Boolean          gnu_style;
extern Name_set         hashtab;
extern Name             host_arch;
extern Name             host_mach;
extern int              line_number;
extern char             *make_state_lockfile;
extern Boolean          make_word_mentioned;
extern Makefile_type    makefile_type;
extern char             mbs_buffer[];
extern Name             path_name;
extern Boolean          posix;
extern Name             query;
extern Boolean          query_mentioned;
extern Name             hat;
extern Boolean          reading_environment;
extern Name             shell_name;
extern Boolean          svr4;
extern Name             target_arch;
extern Name             target_mach;
extern Boolean          tilde_rule;
extern wchar_t          wcs_buffer[];
extern Boolean          working_on_targets;
extern Name             virtual_root;
extern Boolean          vpath_defined;
extern Name             vpath_name;
extern Boolean          make_state_locked;
extern Boolean          out_err_same;
extern pid_t            childPid;

/*
 * RFE 1257407: make does not use fine granularity time info available from stat.
 * High resolution time comparison.
 */

inline int
operator==(const timestruc_t &t1, const timestruc_t &t2) {
        return ((t1.tv_sec == t2.tv_sec) && (t1.tv_nsec == t2.tv_nsec));
}

inline int
operator!=(const timestruc_t &t1, const timestruc_t &t2) {
        return ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec));
}

inline int
operator>(const timestruc_t &t1, const timestruc_t &t2) {
        if (t1.tv_sec == t2.tv_sec) {
                return (t1.tv_nsec > t2.tv_nsec);
        }
        return (t1.tv_sec > t2.tv_sec);
}

inline int
operator>=(const timestruc_t &t1, const timestruc_t &t2) {
        if (t1.tv_sec == t2.tv_sec) {
                return (t1.tv_nsec >= t2.tv_nsec);
        }
        return (t1.tv_sec > t2.tv_sec);
}

inline int
operator<(const timestruc_t &t1, const timestruc_t &t2) {
        if (t1.tv_sec == t2.tv_sec) {
                return (t1.tv_nsec < t2.tv_nsec);
        }
        return (t1.tv_sec < t2.tv_sec);
}

inline int
operator<=(const timestruc_t &t1, const timestruc_t &t2) {
        if (t1.tv_sec == t2.tv_sec) {
                return (t1.tv_nsec <= t2.tv_nsec);
        }
        return (t1.tv_sec < t2.tv_sec);
}

#endif