From e0463df9c3d2ee6155221cc443c571d5da47098a Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Fri, 29 Jun 2012 14:36:07 +0400 Subject: Initial import of DevPro make sources Downloaded from http://dlc.sun.com/osol/devpro/downloads/current/ Licensed under CDDL http://www.opensource.org/licenses/CDDL-1.0 --- usr/src/make_src/Make/bin/make/common/read.cc | 2197 +++++++++++++++++++++++++ 1 file changed, 2197 insertions(+) create mode 100644 usr/src/make_src/Make/bin/make/common/read.cc (limited to 'usr/src/make_src/Make/bin/make/common/read.cc') diff --git a/usr/src/make_src/Make/bin/make/common/read.cc b/usr/src/make_src/Make/bin/make/common/read.cc new file mode 100644 index 0000000..586d609 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/read.cc @@ -0,0 +1,2197 @@ +/* + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)read.cc 1.64 06/12/12 + */ + +#pragma ident "@(#)read.cc 1.64 06/12/12" + +/* + * read.c + * + * This file contains the makefile reader. + */ + +/* + * Included files + */ +#include /* alloca() */ +#include /* errno */ +#include /* fcntl() */ +#include +#include /* expand_value(), expand_macro() */ +#include /* getmem() */ +#include /* get_next_block_fn() */ +#include /* read() */ +#include /* read(), unlink() */ + +#if defined(HP_UX) || defined(linux) +#include +extern "C" Avo_err *avo_find_run_dir(char **dirp); +#endif + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +static int line_started_with_space=0; // Used to diagnose spaces instead of tabs + +/* + * File table of contents + */ +static void parse_makefile(register Name true_makefile_name, register Source source); +static Source push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source); +extern void enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen); +extern Name normalize_name(register wchar_t *name_string, register int length); + +/* + * read_simple_file(makefile_name, chase_path, doname_it, + * complain, must_exist, report_file, lock_makefile) + * + * Make the makefile and setup to read it. Actually read it if it is stdio + * + * Return value: + * false if the read failed + * + * Parameters: + * makefile_name Name of the file to read + * chase_path Use the makefile path when opening file + * doname_it Call doname() to build the file first + * complain Print message if doname/open fails + * must_exist Generate fatal if file is missing + * report_file Report file when running -P + * lock_makefile Lock the makefile when reading + * + * Static variables used: + * + * Global variables used: + * do_not_exec_rule Is -n on? + * file_being_read Set to the name of the new file + * line_number The number of the current makefile line + * makefiles_used A list of all makefiles used, appended to + */ + + +Boolean +read_simple_file(register Name makefile_name, register Boolean chase_path, register Boolean doname_it, Boolean complain, Boolean must_exist, Boolean report_file, Boolean lock_makefile) +{ + static short max_include_depth; + register Property makefile = maybe_append_prop(makefile_name, + makefile_prop); + Boolean forget_after_parse = false; + static pathpt makefile_path; + register int n; + char *path; + register Source source = ALLOC(Source); + Property orig_makefile = makefile; + Dependency *dpp; + Dependency dp; + register int length; + wchar_t *previous_file_being_read = file_being_read; + int previous_line_number = line_number; + wchar_t previous_current_makefile[MAXPATHLEN]; + Makefile_type save_makefile_type; + Name normalized_makefile_name; + register wchar_t *string_start; + register wchar_t *string_end; + + +#if defined(HP_UX) || defined(linux) + Avo_err *findrundir_err; + char *run_dir, makerules_dir[BUFSIZ]; +#endif + + wchar_t * wcb = get_wstring(makefile_name->string_mb); + +#ifdef NSE + if (report_file){ + wscpy(previous_current_makefile, current_makefile); + wscpy(current_makefile, wcb); + } +#endif + if (max_include_depth++ >= 40) { + fatal(catgets(catd, 1, 66, "Too many nested include statements")); + } + if (makefile->body.makefile.contents != NULL) { + retmem(makefile->body.makefile.contents); + } + source->inp_buf = + source->inp_buf_ptr = + source->inp_buf_end = NULL; + source->error_converting = false; + makefile->body.makefile.contents = NULL; + makefile->body.makefile.size = 0; + if ((makefile_name->hash.length != 1) || + (wcb[0] != (int) hyphen_char)) { + if ((makefile->body.makefile.contents == NULL) && + (doname_it)) { + if (makefile_path == NULL) { + add_dir_to_path(".", + &makefile_path, + -1); +#ifdef SUN5_0 + add_dir_to_path(NOCATGETS("/usr/share/lib/make"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/etc/default"), + &makefile_path, + -1); +#elif defined(HP_UX) + findrundir_err = avo_find_run_dir(&run_dir); + if (! findrundir_err) { + (void) sprintf(makerules_dir, NOCATGETS("%s/../share/lib/make"), run_dir); + add_dir_to_path(makerules_dir, + &makefile_path, + -1); + } + + add_dir_to_path(NOCATGETS("/opt/SUNWspro/share/lib/make"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/usr/share/lib/make"), + &makefile_path, + -1); +#elif defined(linux) + findrundir_err = avo_find_run_dir(&run_dir); + if (! findrundir_err) { + (void) sprintf(makerules_dir, NOCATGETS("%s/../lib"), run_dir); + add_dir_to_path(makerules_dir, + &makefile_path, + -1); + } + + add_dir_to_path(NOCATGETS("/usr/SUNWspro/lib"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/opt/SUNWspro/share/lib/make"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/usr/share/lib/make"), + &makefile_path, + -1); +#else + add_dir_to_path(NOCATGETS("/usr/include/make"), + &makefile_path, + -1); +#endif + } + save_makefile_type = makefile_type; + makefile_type = reading_nothing; + if (doname(makefile_name, true, false) == build_dont_know) { + /* Try normalized filename */ + string_start=get_wstring(makefile_name->string_mb); + for (string_end=string_start+1; *string_end != NULL; string_end++); + normalized_makefile_name=normalize_name(string_start, string_end - string_start); + if ((strcmp(makefile_name->string_mb, normalized_makefile_name->string_mb) == 0) || + (doname(normalized_makefile_name, true, false) == build_dont_know)) { + n = access_vroot(makefile_name->string_mb, + 4, + chase_path ? + makefile_path : NULL, + VROOT_DEFAULT); + if (n == 0) { + get_vroot_path((char **) NULL, + &path, + (char **) NULL); + if ((path[0] == (int) period_char) && + (path[1] == (int) slash_char)) { + path += 2; + } + MBSTOWCS(wcs_buffer, path); + makefile_name = GETNAME(wcs_buffer, + FIND_LENGTH); + } + } + retmem(string_start); + /* + * Commented out: retmem_mb(normalized_makefile_name->string_mb); + * We have to return this memory, but it seems to trigger a bug + * in dmake or in Sun C++ 5.7 compiler (it works ok if this code + * is compiled using Sun C++ 5.6). + */ + // retmem_mb(normalized_makefile_name->string_mb); + } + makefile_type = save_makefile_type; + } + source->string.free_after_use = false; + source->previous = NULL; + source->already_expanded = false; + /* Lock the file for read, but not when -n. */ + if (lock_makefile && + !do_not_exec_rule) { + + make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(NOCATGETS(".lock")) + 1); + (void) sprintf(make_state_lockfile, + NOCATGETS("%s.lock"), + make_state->string_mb); + (void) file_lock(make_state->string_mb, + make_state_lockfile, + (int *) &make_state_locked, + 0); + if(!make_state_locked) { + printf(NOCATGETS("-- NO LOCKING for read\n")); + retmem_mb(make_state_lockfile); + make_state_lockfile = 0; + return failed; + } + } + if (makefile->body.makefile.contents == NULL) { + save_makefile_type = makefile_type; + makefile_type = reading_nothing; + if ((doname_it) && + (doname(makefile_name, true, false) == build_failed)) { + if (complain) { + (void) fprintf(stderr, +#ifdef DISTRIBUTED + catgets(catd, 1, 67, "dmake: Couldn't dmake `%s'\n"), +#else + catgets(catd, 1, 237, "make: Couldn't make `%s'\n"), +#endif + makefile_name->string_mb); + } + max_include_depth--; + makefile_type = save_makefile_type; + return failed; + } + makefile_type = save_makefile_type; + // + // Before calling exists() make sure that we have the right timestamp + // + makefile_name->stat.time = file_no_time; + + if (exists(makefile_name) == file_doesnt_exist) { + if (complain || + (makefile_name->stat.stat_errno != ENOENT)) { + if (must_exist) { + fatal(catgets(catd, 1, 68, "Can't find `%s': %s"), + makefile_name->string_mb, + errmsg(makefile_name-> + stat.stat_errno)); + } else { + warning(catgets(catd, 1, 69, "Can't find `%s': %s"), + makefile_name->string_mb, + errmsg(makefile_name-> + stat.stat_errno)); + } + } + max_include_depth--; + if(make_state_locked && (make_state_lockfile != NULL)) { + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } + retmem(wcb); + retmem_mb((char *)source); + return failed; + } + /* + * These values are the size and bytes of + * the MULTI-BYTE makefile. + */ + orig_makefile->body.makefile.size = + makefile->body.makefile.size = + source->bytes_left_in_file = + makefile_name->stat.size; + if (report_file) { + for (dpp = &makefiles_used; + *dpp != NULL; + dpp = &(*dpp)->next); + dp = ALLOC(Dependency); + dp->next = NULL; + dp->name = makefile_name; + dp->automatic = false; + dp->stale = false; + dp->built = false; + *dpp = dp; + } + source->fd = open_vroot(makefile_name->string_mb, + O_RDONLY, + 0, + NULL, + VROOT_DEFAULT); + if (source->fd < 0) { + if (complain || (errno != ENOENT)) { + if (must_exist) { + fatal(catgets(catd, 1, 70, "Can't open `%s': %s"), + makefile_name->string_mb, + errmsg(errno)); + } else { + warning(catgets(catd, 1, 71, "Can't open `%s': %s"), + makefile_name->string_mb, + errmsg(errno)); + } + } + max_include_depth--; + return failed; + } + (void) fcntl(source->fd, F_SETFD, 1); + orig_makefile->body.makefile.contents = + makefile->body.makefile.contents = + source->string.text.p = + source->string.buffer.start = + ALLOC_WC((int) (makefile_name->stat.size + 2)); + if (makefile_type == reading_cpp_file) { + forget_after_parse = true; + } + source->string.text.end = source->string.text.p; + source->string.buffer.end = + source->string.text.p + makefile_name->stat.size; + } else { + /* Do we ever reach here? */ + source->fd = -1; + source->string.text.p = + source->string.buffer.start = + makefile->body.makefile.contents; + source->string.text.end = + source->string.buffer.end = + source->string.text.p + makefile->body.makefile.size; + source->bytes_left_in_file = + makefile->body.makefile.size; + } + file_being_read = wcb; + } else { + char *stdin_text_p; + char *stdin_text_end; + char *stdin_buffer_start; + char *stdin_buffer_end; + char *p_mb; + int num_mb_chars; + size_t num_wc_chars; + + MBSTOWCS(wcs_buffer, NOCATGETS("Standard in")); + makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); + /* + * Memory to read standard in, then convert it + * to wide char strings. + */ + stdin_buffer_start = + stdin_text_p = getmem(length = 1024); + stdin_buffer_end = stdin_text_p + length; + MBSTOWCS(wcs_buffer, NOCATGETS("standard input")); + file_being_read = (wchar_t *) wsdup(wcs_buffer); + line_number = 0; + while ((n = read(fileno(stdin), + stdin_text_p, + length)) > 0) { + length -= n; + stdin_text_p += n; + if (length == 0) { + p_mb = getmem(length = 1024 + + (stdin_buffer_end - + stdin_buffer_start)); + (void) strncpy(p_mb, + stdin_buffer_start, + (stdin_buffer_end - + stdin_buffer_start)); + retmem_mb(stdin_buffer_start); + stdin_text_p = p_mb + + (stdin_buffer_end - stdin_buffer_start); + stdin_buffer_start = p_mb; + stdin_buffer_end = + stdin_buffer_start + length; + length = 1024; + } + } + if (n < 0) { + fatal(catgets(catd, 1, 72, "Error reading standard input: %s"), + errmsg(errno)); + } + stdin_text_p = stdin_buffer_start; + stdin_text_end = stdin_buffer_end - length; + num_mb_chars = stdin_text_end - stdin_text_p; + + /* + * Now, convert the sequence of multibyte chars into + * a sequence of corresponding wide character codes. + */ + source->string.free_after_use = false; + source->previous = NULL; + source->bytes_left_in_file = 0; + source->fd = -1; + source->already_expanded = false; + source->string.buffer.start = + source->string.text.p = ALLOC_WC(num_mb_chars + 1); + source->string.buffer.end = + source->string.text.p + num_mb_chars; + num_wc_chars = mbstowcs(source->string.text.p, + stdin_text_p, + num_mb_chars); + if ((int) num_wc_chars >= 0) { + source->string.text.end = + source->string.text.p + num_wc_chars; + } + (void) retmem_mb(stdin_text_p); + } + line_number = 1; + if (trace_reader) { + (void) printf(catgets(catd, 1, 73, ">>>>>>>>>>>>>>>> Reading makefile %s\n"), + makefile_name->string_mb); + } + parse_makefile(makefile_name, source); + if (trace_reader) { + (void) printf(catgets(catd, 1, 74, ">>>>>>>>>>>>>>>> End of makefile %s\n"), + makefile_name->string_mb); + } +#ifdef NSE + if (report_file && (previous_current_makefile[0] != NULL)) { + wscpy(current_makefile, previous_current_makefile); + } +#endif + if(file_being_read) { + retmem(file_being_read); + } + file_being_read = previous_file_being_read; + line_number = previous_line_number; + makefile_type = reading_nothing; + max_include_depth--; + if (make_state_locked) { + /* Unlock .make.state. */ + unlink(make_state_lockfile); + make_state_locked = false; + retmem_mb(make_state_lockfile); + } + if (forget_after_parse) { + retmem(makefile->body.makefile.contents); + makefile->body.makefile.contents = NULL; + } + retmem_mb((char *)source); + return succeeded; +} + +/* + * parse_makefile(true_makefile_name, source) + * + * Strings are read from Sources. + * When macros are found, their values are represented by a + * Source that is pushed on a stack. At end of string + * (that is returned from GET_CHAR() as 0), the block is popped. + * + * Parameters: + * true_makefile_name The name of makefile we are parsing + * source The source block to read from + * + * Global variables used: + * do_not_exec_rule Is -n on? + * line_number The number of the current makefile line + * makefile_type What kind of makefile are we reading? + * empty_name The Name "" + */ +static void +parse_makefile(register Name true_makefile_name, register Source source) +{ +/* + char mb_buffer[MB_LEN_MAX]; + */ + register wchar_t *source_p; + register wchar_t *source_end; + register wchar_t *string_start; + wchar_t *string_end; + register Boolean macro_seen_in_string; + Boolean append; + String_rec name_string; + wchar_t name_buffer[STRING_BUFFER_LENGTH]; + register int distance; + register int paren_count; + int brace_count; + int char_number; + Cmd_line command; + Cmd_line command_tail; + Name macro_value; + + Name_vector_rec target; + Name_vector_rec depes; + Name_vector_rec extra_name_vector; + Name_vector current_names; + Name_vector extra_names = &extra_name_vector; + Name_vector nvp; + Boolean target_group_seen; + + register Reader_state state; + register Reader_state on_eoln_state; + register Separator separator; + + wchar_t buffer[4 * STRING_BUFFER_LENGTH]; + Source extrap; + + Boolean save_do_not_exec_rule = do_not_exec_rule; + Name makefile_name; + + static Name sh_name; + static Name shell_name; + int i; + + static wchar_t include_space[10]; + static wchar_t include_tab[10]; + int tmp_bytes_left_in_string; + Boolean tmp_maybe_include = false; + int emptycount = 0; + Boolean first_target; + + String_rec include_name; + wchar_t include_buffer[STRING_BUFFER_LENGTH]; + + target.next = depes.next = NULL; + /* Move some values from their struct to register declared locals */ + CACHE_SOURCE(0); + + start_new_line: + /* + * Read whitespace on old line. Leave pointer on first char on + * next line. + */ + first_target = true; + on_eoln_state = exit_state; +/* + for (WCTOMB(mb_buffer, GET_CHAR()); + 1; + source_p++, WCTOMB(mb_buffer, GET_CHAR())) + switch (mb_buffer[0]) { + */ + for (char_number=0; 1; source_p++,char_number++) switch (GET_CHAR()) { + case nul_char: + /* End of this string. Pop it and return to the previous one */ + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case newline_char: + end_of_line: + source_p++; + if (source->fd >= 0) { + line_number++; + } + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + /* Go back to the top of this loop */ + goto start_new_line; + case newline_char: + case numbersign_char: + case dollar_char: + case space_char: + case tab_char: + /* + * Go back to the top of this loop since the + * new line does not start with a regular char. + */ + goto start_new_line; + default: + /* We found the first proper char on the new line */ + goto start_new_line_no_skip; + } + case space_char: + if (char_number == 0) + line_started_with_space=line_number; + case tab_char: + /* Whitespace. Just keep going in this loop */ + break; + case numbersign_char: + /* Comment. Skip over it */ + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + } + source_p--; + break; + case backslash_char: + /* Comments can be continued */ + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + source_p--; + break; + } + } + if(*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + /* + * After we skip the comment we go to + * the end of line handler since end of + * line terminates comments. + */ + goto end_of_line; + } + } + case dollar_char: + /* Macro reference */ + if (source->already_expanded) { + /* + * If we are reading from the expansion of a + * macro we already expanded everything enough. + */ + goto start_new_line_no_skip; + } + /* + * Expand the value and push the Source on the stack of + * things being read. + */ + source_p++; + UNCACHE_SOURCE(); + { + Source t = (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(1); + break; + default: + /* We found the first proper char on the new line */ + goto start_new_line_no_skip; + } + + /* + * We found the first normal char (one that starts an identifier) + * on the newline. + */ +start_new_line_no_skip: + /* Inspect that first char to see if it maybe is special anyway */ + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + goto start_new_line_no_skip; + case newline_char: + /* Just in case */ + goto start_new_line; + case exclam_char: + /* Evaluate the line before it is read */ + string_start = source_p + 1; + macro_seen_in_string = false; + /* Stuff the line in a string so we can eval it. */ + for (; 1; source_p++) { + switch (GET_CHAR()) { + case newline_char: + goto eoln_1; + case nul_char: + if (source->fd > 0) { + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK( + name_string, name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + break; + } + eoln_1: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + extrap = (Source) + alloca((int) sizeof (Source_rec)); + extrap->string.buffer.start = NULL; + extrap->inp_buf = + extrap->inp_buf_ptr = + extrap->inp_buf_end = NULL; + extrap->error_converting = false; + if (*source_p == (int) nul_char) { + source_p++; + } + /* Eval the macro */ + expand_value(GETNAME(name_string.buffer.start, + FIND_LENGTH), + &extrap->string, + false); + if (name_string.free_after_use) { + retmem(name_string.buffer.start); + } + UNCACHE_SOURCE(); + extrap->string.text.p = + extrap->string.buffer.start; + extrap->fd = -1; + /* And push the value */ + extrap->previous = source; + source = extrap; + CACHE_SOURCE(0); + goto line_evald; + } + } + default: + goto line_evald; + } + + /* We now have a line we can start reading */ + line_evald: + if (source == NULL) { + GOTO_STATE(exit_state); + } + /* Check if this is an include command */ + if ((makefile_type == reading_makefile) && + !source->already_expanded) { + if (include_space[0] == (int) nul_char) { + MBSTOWCS(include_space, NOCATGETS("include ")); + MBSTOWCS(include_tab, NOCATGETS("include\t")); + } + if ((IS_WEQUALN(source_p, include_space, 8)) || + (IS_WEQUALN(source_p, include_tab, 8))) { + source_p += 7; + if (iswspace(*source_p)) { + Makefile_type save_makefile_type; + wchar_t *name_start; + int name_length; + + /* + * Yes, this is an include. + * Skip spaces to get to the filename. + */ + while (iswspace(*source_p) || + (*source_p == (int) nul_char)) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + + default: + source_p++; + break; + } + } + + string_start = source_p; + /* Find the end of the filename */ + macro_seen_in_string = false; + while (!iswspace(*source_p) || + (*source_p == (int) nul_char)) { + switch (GET_CHAR()) { + case nul_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + GET_NEXT_BLOCK(source); + string_start = source_p; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + + default: + source_p++; + break; + } + } + + source->string.text.p = source_p; + if (macro_seen_in_string) { + append_string(string_start, + &name_string, + source_p - string_start); + name_start = name_string.buffer.start; + name_length = name_string.text.p - name_start; + } else { + name_start = string_start; + name_length = source_p - string_start; + } + + /* Strip "./" from the head of the name */ + if ((name_start[0] == (int) period_char) && + (name_start[1] == (int) slash_char)) { + name_start += 2; + name_length -= 2; + } + /* if include file name is surrounded by double quotes */ + if ((name_start[0] == (int) doublequote_char) && + (name_start[name_length - 1] == (int) doublequote_char)) { + name_start += 1; + name_length -= 2; + + /* if name does not begin with a slash char */ + if (name_start[0] != (int) slash_char) { + if ((name_start[0] == (int) period_char) && + (name_start[1] == (int) slash_char)) { + name_start += 2; + name_length -= 2; + } + + INIT_STRING_FROM_STACK(include_name, include_buffer); + APPEND_NAME(true_makefile_name, + &include_name, + true_makefile_name->hash.length); + + wchar_t *slash = wsrchr(include_name.buffer.start, (int) slash_char); + if (slash != NULL) { + include_name.text.p = slash + 1; + append_string(name_start, + &include_name, + name_length); + + name_start = include_name.buffer.start; + name_length = include_name.text.p - name_start; + } + } + } + + /* Even when we run -n we want to create makefiles */ + do_not_exec_rule = false; + makefile_name = GETNAME(name_start, name_length); + if (makefile_name->dollar) { + String_rec destination; + wchar_t buffer[STRING_BUFFER_LENGTH]; + wchar_t *p; + wchar_t *q; + + INIT_STRING_FROM_STACK(destination, buffer); + expand_value(makefile_name, + &destination, + false); + for (p = destination.buffer.start; + (*p != (int) nul_char) && iswspace(*p); + p++); + for (q = p; + (*q != (int) nul_char) && !iswspace(*q); + q++); + makefile_name = GETNAME(p, q-p); + if (destination.free_after_use) { + retmem(destination.buffer.start); + } + } + source_p++; + UNCACHE_SOURCE(); + /* Read the file */ + save_makefile_type = makefile_type; + if (read_simple_file(makefile_name, + true, + true, + true, + false, + true, + false) == failed) { + fatal_reader(catgets(catd, 1, 75, "Read of include file `%s' failed"), + makefile_name->string_mb); + } + makefile_type = save_makefile_type; + do_not_exec_rule = save_do_not_exec_rule; + CACHE_SOURCE(0); + goto start_new_line; + } else { + source_p -= 7; + } + } else { + /* Check if the word include was split across 8K boundary. */ + + tmp_bytes_left_in_string = source->string.text.end - source_p; + if (tmp_bytes_left_in_string < 8) { + tmp_maybe_include = false; + if (IS_WEQUALN(source_p, + include_space, + tmp_bytes_left_in_string)) { + tmp_maybe_include = true; + } + if (tmp_maybe_include) { + GET_NEXT_BLOCK(source); + tmp_maybe_include = false; + goto line_evald; + } + } + } + } + + /* Reset the status in preparation for the new line */ + for (nvp = ⌖ nvp != NULL; nvp = nvp->next) { + nvp->used = 0; + } + for (nvp = &depes; nvp != NULL; nvp = nvp->next) { + nvp->used = 0; + } + target_group_seen = false; + command = command_tail = NULL; + macro_value = NULL; + append = false; + current_names = ⌖ + SET_STATE(scan_name_state); + on_eoln_state = illegal_eoln_state; + separator = none_seen; + + /* The state machine starts here */ + enter_state: + while (1) switch (state) { + +/**************************************************************** + * Scan name state + */ +case scan_name_state: + /* Scan an identifier. We skip over chars until we find a break char */ + /* First skip white space. */ + for (; 1; source_p++) switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case newline_char: + /* We found the end of the line. */ + /* Do postprocessing or return error */ + source_p++; + if (source->fd >= 0) { + line_number++; + } + GOTO_STATE(on_eoln_state); + case backslash_char: + /* Continuation */ + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } else { + source_p--; + } + break; + case tab_char: + case space_char: + /* Whitespace is skipped */ + break; + case numbersign_char: + /* Comment. Skip over it */ + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + } + source_p--; + break; + case backslash_char: + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + source_p--; + break; + } + } + if(*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + source_p++; + if (source->fd >= 0) { + line_number++; + } + GOTO_STATE(on_eoln_state); + } + } + case dollar_char: + /* Macro reference. Expand and push value */ + if (source->already_expanded) { + goto scan_name; + } + source_p++; + UNCACHE_SOURCE(); + { + Source t = (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(1); + break; + default: + /* End of white space */ + goto scan_name; + } + + /* First proper identifier character */ + scan_name: + + string_start = source_p; + paren_count = brace_count = 0; + macro_seen_in_string = false; + resume_name_scan: + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + /* Save what we have seen so far of the identifier */ + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + /* Get more text to read */ + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case newline_char: + if (paren_count > 0) { + fatal_reader(catgets(catd, 1, 76, "Unmatched `(' on line")); + } + if (brace_count > 0) { + fatal_reader(catgets(catd, 1, 77, "Unmatched `{' on line")); + } + source_p++; + /* Enter name */ + current_names = enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p - 1, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) sizeof (Name_vector_rec)); + } + /* Do postprocessing or return error */ + if (source->fd >= 0) { + line_number++; + } + GOTO_STATE(on_eoln_state); + case backslash_char: + /* Check if this is a quoting backslash */ + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + macro_seen_in_string = true; + } + append_string(string_start, + &name_string, + source_p - string_start); + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + *source_p = (int) space_char; + string_start = source_p; + goto resume_name_scan; + } else { + string_start = source_p; + break; + } + break; + case numbersign_char: + if (paren_count + brace_count > 0) { + break; + } + fatal_reader(catgets(catd, 1, 78, "Unexpected comment seen")); + case dollar_char: + if (source->already_expanded) { + break; + } + /* Save the identifier so far */ + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + /* Eval and push the macro */ + source_p++; + UNCACHE_SOURCE(); + { + Source t = + (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(1); + string_start = source_p + 1; + break; + case parenleft_char: + paren_count++; + break; + case parenright_char: + if (--paren_count < 0) { + fatal_reader(catgets(catd, 1, 79, "Unmatched `)' on line")); + } + break; + case braceleft_char: + brace_count++; + break; + case braceright_char: + if (--brace_count < 0) { + fatal_reader(catgets(catd, 1, 80, "Unmatched `}' on line")); + } + break; + case ampersand_char: + case greater_char: + case bar_char: + if (paren_count + brace_count == 0) { + source_p++; + } + /* Fall into */ + case tab_char: + case space_char: + if (paren_count + brace_count > 0) { + break; + } + current_names = enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) sizeof (Name_vector_rec)); + } + goto enter_state; + case colon_char: + if (paren_count + brace_count > 0) { + break; + } + if (separator == conditional_seen) { + break; + } +/** POSIX **/ +#if 0 + if(posix) { + emptycount = 0; + } +#endif +/** END POSIX **/ + /* End of the target list. We now start reading */ + /* dependencies or a conditional assignment */ + if (separator != none_seen) { + fatal_reader(catgets(catd, 1, 81, "Extra `:', `::', or `:=' on dependency line")); + } + /* Enter the last target */ + if ((string_start != source_p) || + macro_seen_in_string) { + current_names = + enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) + sizeof (Name_vector_rec)); + } + } + /* Check if it is ":" "::" or ":=" */ + scan_colon_label: + switch (*++source_p) { + case nul_char: + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(enter_dependencies_state); + } + goto scan_colon_label; + case equal_char: + if(svr4) { + fatal_reader(catgets(catd, 1, 82, "syntax error")); + } + separator = conditional_seen; + source_p++; + current_names = &depes; + GOTO_STATE(scan_name_state); + case colon_char: + separator = two_colon; + source_p++; + break; + default: + separator = one_colon; + } + current_names = &depes; + on_eoln_state = enter_dependencies_state; + GOTO_STATE(scan_name_state); + case semicolon_char: + if (paren_count + brace_count > 0) { + break; + } + /* End of reading names. Start reading the rule */ + if ((separator != one_colon) && + (separator != two_colon)) { + fatal_reader(catgets(catd, 1, 83, "Unexpected command seen")); + } + /* Enter the last dependency */ + if ((string_start != source_p) || + macro_seen_in_string) { + current_names = + enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) + sizeof (Name_vector_rec)); + } + } + source_p++; + /* Make sure to enter a rule even if the is */ + /* no text here */ + command = command_tail = ALLOC(Cmd_line); + command->next = NULL; + command->command_line = empty_name; + command->make_refd = false; + command->ignore_command_dependency = false; + command->assign = false; + command->ignore_error = false; + command->silent = false; + + GOTO_STATE(scan_command_state); + case plus_char: + /* + ** following code drops the target separator plus char if it starts + ** a line. + */ + if(first_target && !macro_seen_in_string && + source_p == string_start) { + for (; 1; source_p++) + switch (GET_CHAR()) { + case nul_char: + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case plus_char: + source_p++; + while (*source_p == (int) nul_char) { + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + GET_NEXT_BLOCK(source); + string_start = source_p; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p == (int) tab_char || + *source_p == (int) space_char) { + macro_seen_in_string = false; + string_start = source_p + 1; + } else { + goto resume_name_scan; + } + break; + case tab_char: + case space_char: + string_start = source_p + 1; + break; + default: + goto resume_name_scan; + } + } + if (paren_count + brace_count > 0) { + break; + } + /* We found "+=" construct */ + if (source_p != string_start) { + /* "+" is not a break char. */ + /* Ignore it if it is part of an identifier */ + source_p++; + goto resume_name_scan; + } + /* Make sure the "+" is followed by a "=" */ + scan_append: + switch (*++source_p) { + case nul_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + source_p--; + string_start = source_p; + if (source == NULL) { + GOTO_STATE(illegal_eoln_state); + } + goto scan_append; + case equal_char: + if(!svr4) { + append = true; + } else { + fatal_reader(catgets(catd, 1, 84, "Must be a separator on rules")); + } + break; + default: + /* The "+" just starts a regular name. */ + /* Start reading that name */ + goto resume_name_scan; + } + /* Fall into */ + case equal_char: + if (paren_count + brace_count > 0) { + break; + } + /* We found macro assignment. */ + /* Check if it is legal and if it is appending */ + switch (separator) { + case none_seen: + separator = equal_seen; + on_eoln_state = enter_equal_state; + break; + case conditional_seen: + on_eoln_state = enter_conditional_state; + break; + default: + /* Reader must special check for "MACRO:sh=" */ + /* notation */ + if (sh_name == NULL) { + MBSTOWCS(wcs_buffer, NOCATGETS("sh")); + sh_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("shell")); + shell_name = GETNAME(wcs_buffer, FIND_LENGTH); + } + + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start + ); + + if ( (((target.used == 1) && + (depes.used == 1) && + (depes.names[0] == sh_name)) || + ((target.used == 1) && + (depes.used == 0) && + (separator == one_colon) && + (GETNAME(name_string.buffer.start,FIND_LENGTH) == sh_name))) && + (!svr4)) { + String_rec macro_name; + wchar_t buffer[100]; + + INIT_STRING_FROM_STACK(macro_name, + buffer); + APPEND_NAME(target.names[0], + ¯o_name, + FIND_LENGTH); + append_char((int) colon_char, + ¯o_name); + APPEND_NAME(sh_name, + ¯o_name, + FIND_LENGTH); + target.names[0] = + GETNAME(macro_name.buffer.start, + FIND_LENGTH); + separator = equal_seen; + on_eoln_state = enter_equal_state; + break; + } else if ( (((target.used == 1) && + (depes.used == 1) && + (depes.names[0] == shell_name)) || + ((target.used == 1) && + (depes.used == 0) && + (separator == one_colon) && + (GETNAME(name_string.buffer.start,FIND_LENGTH) == shell_name))) && + (!svr4)) { + String_rec macro_name; + wchar_t buffer[100]; + + INIT_STRING_FROM_STACK(macro_name, + buffer); + APPEND_NAME(target.names[0], + ¯o_name, + FIND_LENGTH); + append_char((int) colon_char, + ¯o_name); + APPEND_NAME(shell_name, + ¯o_name, + FIND_LENGTH); + target.names[0] = + GETNAME(macro_name.buffer.start, + FIND_LENGTH); + separator = equal_seen; + on_eoln_state = enter_equal_state; + break; + } + if(svr4) { + fatal_reader(catgets(catd, 1, 85, "syntax error")); + } + else { + fatal_reader(catgets(catd, 1, 86, "Macro assignment on dependency line")); + } + } + if (append) { + source_p--; + } + /* Enter the macro name */ + if ((string_start != source_p) || + macro_seen_in_string) { + current_names = + enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) + sizeof (Name_vector_rec)); + } + } + if (append) { + source_p++; + } + macro_value = NULL; + source_p++; + distance = 0; + /* Skip whitespace to the start of the value */ + macro_seen_in_string = false; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case backslash_char: + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p != (int) newline_char) { + if (!macro_seen_in_string) { + macro_seen_in_string = + true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_char((int) + backslash_char, + &name_string); + append_char(*source_p, + &name_string); + string_start = source_p+1; + goto macro_value_start; + } else { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + case numbersign_char: + string_start = source_p; + goto macro_value_end; + case tab_char: + case space_char: + break; + default: + string_start = source_p; + goto macro_value_start; + } + } + macro_value_start: + /* Find the end of the value */ + for (; 1; source_p++) { + if (distance != 0) { + *source_p = *(source_p + distance); + } + switch (GET_CHAR()) { + case nul_char: + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case backslash_char: + source_p++; + if (distance != 0) { + *source_p = + *(source_p + distance); + } + if (*source_p == (int) nul_char) { + if (!macro_seen_in_string) { + macro_seen_in_string = + true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + +/* BID_1225561 */ + *(source_p - 1) = (int) space_char; + append_string(string_start, + &name_string, + source_p - + string_start - 1); + GET_NEXT_BLOCK(source); + string_start = source_p; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (distance != 0) { + *source_p = + *(source_p + + distance); + } + if (*source_p == (int) newline_char) { + append_char((int) space_char, &name_string); + } else { + append_char((int) backslash_char, &name_string); + } +/****************/ + } + if (*source_p == (int) newline_char) { + source_p--; + line_number++; + distance++; + *source_p = (int) space_char; + while ((*(source_p + + distance + 1) == + (int) tab_char) || + (*(source_p + + distance + 1) == + (int) space_char)) { + distance++; + } + } + break; + case newline_char: + case numbersign_char: + goto macro_value_end; + } + } + macro_value_end: + /* Complete the value in the string */ + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + if (name_string.buffer.start != name_string.text.p) { + macro_value = + GETNAME(name_string.buffer.start, + FIND_LENGTH); + } + if (name_string.free_after_use) { + retmem(name_string.buffer.start); + } + for (; distance > 0; distance--) { + *source_p++ = (int) space_char; + } + GOTO_STATE(on_eoln_state); + } + } + +/**************************************************************** + * enter dependencies state + */ + case enter_dependencies_state: + enter_dependencies_label: +/* Expects pointer on first non whitespace char after last dependency. (On */ +/* next line.) We end up here after having read a "targets : dependencies" */ +/* line. The state checks if there is a rule to read and if so dispatches */ +/* to scan_command_state scan_command_state reads one rule line and the */ +/* returns here */ + + /* First check if the first char on the next line is special */ + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + break; + } + goto enter_dependencies_label; + case exclam_char: + /* The line should be evaluate before it is read */ + macro_seen_in_string = false; + string_start = source_p + 1; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case newline_char: + goto eoln_2; + case nul_char: + if (source->fd > 0) { + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + break; + } + eoln_2: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + extrap = (Source) + alloca((int) sizeof (Source_rec)); + extrap->string.buffer.start = NULL; + extrap->inp_buf = + extrap->inp_buf_ptr = + extrap->inp_buf_end = NULL; + extrap->error_converting = false; + expand_value(GETNAME(name_string.buffer.start, + FIND_LENGTH), + &extrap->string, + false); + if (name_string.free_after_use) { + retmem(name_string.buffer.start); + } + UNCACHE_SOURCE(); + extrap->string.text.p = + extrap->string.buffer.start; + extrap->fd = -1; + extrap->previous = source; + source = extrap; + CACHE_SOURCE(0); + goto enter_dependencies_label; + } + } + case dollar_char: + if (source->already_expanded) { + break; + } + source_p++; + UNCACHE_SOURCE(); + { + Source t = (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(0); + goto enter_dependencies_label; + case numbersign_char: + if (makefile_type != reading_makefile) { + source_p++; + GOTO_STATE(scan_command_state); + } + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + } + source_p--; + break; + case backslash_char: + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + source_p--; + break; + } + } + if(*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + source_p++; + if (source->fd >= 0) { + line_number++; + } + goto enter_dependencies_label; + } + } + + case tab_char: + GOTO_STATE(scan_command_state); + } + + /* We read all the command lines for the target/dependency line. */ + /* Enter the stuff */ + enter_target_groups_and_dependencies( &target, &depes, command, + separator, target_group_seen); + + goto start_new_line; + +/**************************************************************** + * scan command state + */ +case scan_command_state: + /* We need to read one rule line. Do that and return to */ + /* the enter dependencies state */ + string_start = source_p; + macro_seen_in_string = false; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case backslash_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + string_start = source_p; + goto command_newline; + } + } + append_char((int) backslash_char, &name_string); + append_char(*source_p, &name_string); + if (*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + string_start = source_p; + goto command_newline; + } + } + if (*source_p == (int) tab_char) { + source_p++; + } + } else { + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + string_start = source_p; + goto command_newline; + } + } + } + string_start = source_p; + if ((*source_p == (int) newline_char) || + (*source_p == (int) backslash_char) || + (*source_p == (int) nul_char)) { + source_p--; + } + break; + case newline_char: + command_newline: + if ((string_start != source_p) || + macro_seen_in_string) { + if (macro_seen_in_string) { + append_string(string_start, + &name_string, + source_p - string_start); + string_start = + name_string.buffer.start; + string_end = name_string.text.p; + } else { + string_end = source_p; + } + while ((*string_start != (int) newline_char) && + iswspace(*string_start)){ + string_start++; + } + if ((string_end > string_start) || + (makefile_type == reading_statefile)) { + if (command_tail == NULL) { + command = + command_tail = + ALLOC(Cmd_line); + } else { + command_tail->next = + ALLOC(Cmd_line); + command_tail = + command_tail->next; + } + command_tail->next = NULL; + command_tail->make_refd = false; + command_tail->ignore_command_dependency = false; + command_tail->assign = false; + command_tail->ignore_error = false; + command_tail->silent = false; + command_tail->command_line = + GETNAME(string_start, + string_end - string_start); + if (macro_seen_in_string && + name_string.free_after_use) { + retmem(name_string. + buffer.start); + } + } + } + do { + if ((source != NULL) && (source->fd >= 0)) { + line_number++; + } + if ((source != NULL) && + (*++source_p == (int) nul_char)) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + } while (*source_p == (int) newline_char); + + GOTO_STATE(enter_dependencies_state); + case nul_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(enter_dependencies_state); + } + break; + } + } + +/**************************************************************** + * enter equal state + */ +case enter_equal_state: + if (target.used != 1) { + GOTO_STATE(poorly_formed_macro_state); + } + enter_equal(target.names[0], macro_value, append); + goto start_new_line; + +/**************************************************************** + * enter conditional state + */ +case enter_conditional_state: + if (depes.used != 1) { + GOTO_STATE(poorly_formed_macro_state); + } + for (nvp = ⌖ nvp != NULL; nvp = nvp->next) { + for (i = 0; i < nvp->used; i++) { + enter_conditional(nvp->names[i], + depes.names[0], + macro_value, + append); + } + } + goto start_new_line; + +/**************************************************************** + * Error states + */ +case illegal_bytes_state: + fatal_reader(catgets(catd, 1, 340, "Invalid byte sequence")); +case illegal_eoln_state: + if (line_number > 1) { + if (line_started_with_space == (line_number - 1)) { + line_number--; + fatal_reader(catgets(catd, 1, 90, "Unexpected end of line seen\n\t*** missing separator (did you mean TAB instead of 8 spaces?)")); + } + } + fatal_reader(catgets(catd, 1, 87, "Unexpected end of line seen")); +case poorly_formed_macro_state: + fatal_reader(catgets(catd, 1, 88, "Badly formed macro assignment")); +case exit_state: + return; +default: + fatal_reader(catgets(catd, 1, 89, "Internal error. Unknown reader state")); +} +} + +/* + * push_macro_value(bp, buffer, size, source) + * + * Macro and function that evaluates one macro + * and makes the reader read from the value of it + * + * Return value: + * The source block to read the macro from + * + * Parameters: + * bp The new source block to fill in + * buffer Buffer to read from + * size size of the buffer + * source The old source block + * + * Global variables used: + */ +static Source +push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source) +{ + bp->string.buffer.start = bp->string.text.p = buffer; + bp->string.text.end = NULL; + bp->string.buffer.end = buffer + (size/SIZEOFWCHAR_T); + bp->string.free_after_use = false; + bp->inp_buf = + bp->inp_buf_ptr = + bp->inp_buf_end = NULL; + bp->error_converting = false; + expand_macro(source, &bp->string, (wchar_t *) NULL, false); + bp->string.text.p = bp->string.buffer.start; + + /* 4209588: 'make' doesn't understand a macro with whitespaces in the head as target. + * strip whitespace from the begining of the macro value + */ + while (iswspace(*bp->string.text.p)) { + bp->string.text.p++; + } + + bp->fd = -1; + bp->already_expanded = true; + bp->previous = source; + return bp; +} + +/* + * enter_target_groups_and_dependencies(target, depes, command, separator, + * target_group_seen) + * + * Parameters: + * target Structure that shows the target(s) on the line + * we are currently parsing. This can looks like + * target1 .. targetN : dependencies + * commands + * or + * target1 + .. + targetN : dependencies + * commands + * depes Dependencies + * command Points to the command(s) to be executed for + * this target. + * separator : or :: or := + * target_group_seen Set if we have target1 + .. + targetN + * + * + * After reading the command lines for a target, this routine + * is called to setup the dependencies and the commands for it. + * If the target is a % pattern or part of a target group, then + * the appropriate routines are called. + */ + +void +enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen) +{ + int i; + Boolean reset= true; + Chain target_group_member; + Percent percent_ptr; + + for (; target != NULL; target = target->next) { + for (i = 0; i < target->used; i++) { + if (target->names[i] != NULL) { + if (target_group_seen) { + target_group_member = + find_target_groups(target, i, reset); + if(target_group_member == NULL) { + fatal_reader(catgets(catd, 1, 328, "Unexpected '+' on dependency line")); + } + } + reset = false; + + /* If we saw it in the makefile it must be + * a file */ + target->names[i]->stat.is_file = true; + /* Make sure that we use dependencies + * entered for makefiles */ + target->names[i]->state = build_dont_know; + + /* If the target is special we delegate + * the processing */ + if (target->names[i]->special_reader + != no_special) { + special_reader(target->names[i], + depes, + command); + } + /* Check if this is a "a%b : x%y" type rule */ + else if (target->names[i]->percent) { + percent_ptr = + enter_percent(target->names[i], + target->target_group[i], + depes, command); + if (target_group_seen) { + target_group_member->percent_member = + percent_ptr; + } + } else if (target->names[i]->dollar) { + enter_dyntarget(target->names[i]); + enter_dependencies + (target->names[i], + target->target_group[i], + depes, + command, + separator); + } else { + if (target_group_seen) { + target_group_member->percent_member = + NULL; + } + + enter_dependencies + (target->names[i], + target->target_group[i], + depes, + command, + separator); + } + } + } + } +} + + -- cgit v1.2.3