946 lines
22 KiB
C
946 lines
22 KiB
C
|
#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_) {}
|
||
|
|
||
|
// 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
|