/*
* 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
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* read.c
*
* This file contains the makefile reader.
*/
/*
* Included files
*/
#include <stdarg.h> /* va_list, va_start(), va_end() */
#include <libintl.h>
/*
* Defined macros
*/
/*
* typedefs & structs
*/
/*
* Static variables
*/
/*
* File table of contents
*/
static Name_vector enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names);
/*
* enter_name(string, tail_present, string_start, string_end,
* current_names, extra_names, target_group_seen)
*
* Take one string and enter it as a name. The string is passed in
* two parts. A make string and possibly a C string to append to it.
* The result is stuffed in the vector current_names.
* extra_names points to a vector that is used if current_names overflows.
* This is allocad in the calling routine.
* Here we handle the "lib.a[members]" notation.
*
* Return value:
* The name vector that was used
*
* Parameters:
* tail_present Indicates if both C and make string was passed
* string_start C string
* string_end Pointer to char after last in C string
* string make style string with head of name
* current_names Vector to deposit the name in
* extra_names Where to get next name vector if we run out
* target_group_seen Pointer to boolean that is set if "+" is seen
*
* Global variables used:
* makefile_type When we read a report file we normalize paths
* plus Points to the Name "+"
*/
enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen)
{
register wchar_t *cp;
wchar_t ch;
/* If we were passed a separate tail of the name we append it to the */
/* make string with the rest of it */
if (tail_present) {
}
ch = *string_end;
*string_end = (int) nul_char;
/*
* Check if there are any ( or [ that are not prefixed with $.
* If there are, we have to deal with the lib.a(members) format.
*/
*string_end = ch;
return enter_member_name(string_start,
cp,
}
}
*string_end = ch;
if (makefile_type == reading_cpp_file) {
/* Remove extra ../ constructs if we are reading from a report file */
} else {
/*
* /tolik, fix bug 1197477/
* Normalize every target name before entering.
*/
/*name = GETNAME(string_start, string_end - string_start);*/
}
/* Internalize the name. Detect the name "+" (target group here) */
return current_names;
}
}
/* If the current_names vector is full we patch in the one from */
/* extra_names */
} else {
*extra_names = NULL;
current_names->used = 0;
}
}
*target_group_seen = true;
}
}
return current_names;
}
/*
* enter_member_name(lib_start, member_start, string_end,
* current_names, extra_names)
*
* A string has been found to contain member names.
* (The "lib.a[members]" and "lib.a(members)" notation)
* Handle it pretty much as enter_name() does for simple names.
*
* Return value:
* The name vector that was used
*
* Parameters:
* lib_start Points to the of start of "lib.a(member.o)"
* member_start Points to "member.o" from above string.
* string_end Points to char after last of above string.
* current_names Vector to deposit the name in
* extra_names Where to get next name vector if we run out
*
* Global variables used:
*/
static Name_vector
enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names)
{
wchar_t *memberp;
wchar_t *q;
register int paren_count;
register wchar_t *cq;
/* Internalize the name of the library */
member_start++;
if (*member_start == (int) parenleft_char) {
/* This is really the "lib.a((entries))" format */
entry = true;
member_start++;
}
/* Move the library name to the buffer where we intend to build the */
/* "lib.a(member)" for each member */
while (1) {
/* Skip leading spaces */
for (;
member_start++);
/* Find the end of the member name. Allow nested (). Detect $*/
(member_start < string_end) &&
((*member_start != (int) parenright_char) ||
(paren_count > 0)) &&
!iswspace(*member_start);
*cq++ = *member_start++) {
switch (*member_start) {
case parenleft_char:
paren_count++;
break;
case parenright_char:
paren_count--;
break;
case dollar_char:
has_dollar = true;
}
}
/* Internalize the member name */
*cq = 0;
q = memberp;
}
if ((cq - q > (int) ar_member_name_len) &&
!has_dollar) {
*cq++ = (int) parenright_char;
if (entry) {
*cq++ = (int) parenright_char;
}
cq = q + (int) ar_member_name_len;
}
*cq++ = (int) parenright_char;
if (entry) {
*cq++ = (int) parenright_char;
}
/* Internalize the "lib.a(member)" notation for this member */
if (long_member_name != NULL) {
name->has_long_member_name = true;
}
/* And add the member prop */
if (entry) {
/* "lib.a((entry))" notation */
} else {
/* "lib.a(member)" Notation */
}
/* Handle overflow of current_names */
} else {
if (*extra_names == NULL) {
} else {
*extra_names = NULL;
}
current_names->used = 0;
}
}
while (iswspace(*member_start)) {
member_start++;
}
/* Check if there are more members */
if ((*member_start == (int) parenright_char) ||
(member_start >= string_end)) {
return current_names;
}
}
/* NOTREACHED */
}
/*
* normalize_name(name_string, length)
*
* Take a namestring and remove redundant ../, // and ./ constructs
*
* Return value:
* The normalized name
*
* Parameters:
* name_string Path string to normalize
* length Length of that string
*
* Global variables used:
* dot The Name ".", compared against
* dotdot The Name "..", compared against
*/
{
register wchar_t *string2;
register wchar_t *cdp;
wchar_t *current_component;
register int count;
}
/*
* Copy string removing ./ and //.
* First strip leading ./
*/
while ((length > 1) &&
(name_string[0] == (int) period_char) &&
name_string += 2;
length -= 2;
name_string++;
length--;
}
}
/* Then copy the rest of the string removing /./ & // */
while (length > 0) {
if (((length > 2) &&
(name_string[0] == (int) slash_char) &&
((length == 2) &&
(name_string[0] == (int) slash_char) &&
name_string += 2;
length -= 2;
continue;
}
if ((length > 1) &&
(name_string[0] == (int) slash_char) &&
name_string++;
length--;
continue;
}
*cdp++ = *name_string++;
length--;
}
/*
* Now scan for <name>/../ and remove such combinations iff <name>
* is not another ..
* Each time something is removed, the whole process is restarted.
*/
cdp =
string =
while (length > 0) {
if (((length > 3) &&
(name_string[0] == (int) slash_char) &&
((length == 3) &&
(name_string[0] == (int) slash_char) &&
/* Positioned on the / that starts a /.. sequence */
name_string += 3;
length -= 3;
if (length > 0) {
name_string++; /* skip slash */
length--;
while (length > 0) {
*cdp++ = *name_string++;
length--;
}
}
goto removed_one;
}
}
}
}
length--;
}
} else {
}
return name;
}
/*
* find_target_groups(target_list)
*
* If a "+" was seen when the target list was scanned we need to extract
* the groups. Each target in the name vector that is a member of a
* group gets a pointer to a chain of all the members stuffed in its
* target_group vector slot
*
* Parameters:
* target_list The list of targets that contains "+"
*
* Global variables used:
* plus The Name "+", compared against
*/
{
if (reset) {
target_group = NULL;
clear_target_group = false;
}
/* Scan the list of targets */
/* If the previous target terminated a group */
/* we flush the pointer to that member chain */
if (clear_target_group) {
clear_target_group = false;
target_group = NULL;
}
/* Pick up a pointer to the cell with */
/* the next target */
} else {
}
/* We have four states here :
* 0: No target group started and next element is not "+"
* This is not interesting.
* 1: A target group is being built and the next element
* is not "+". This terminates the group.
* 2: No target group started and the next member is "+"
* This is the first target in a group.
* 3: A target group started and the next member is a "+"
* The group continues.
*/
switch ((target_group ? 1 : 0) +
2 : 0)) {
case 0: /* Not target_group */
break;
case 1: /* Last group member */
/* We need to keep this pointer so */
/* we can stuff it for last member */
clear_target_group = true;
/* fall into */
case 3: /* Middle group member */
/* Add this target to the */
/* current chain */
break;
case 2: /* First group member */
/* Start a new chain */
break;
}
/* Stuff the current chain, if any, in the */
/* targets group slot */
}
return (tail_target_group);
}
/*
* enter_dependencies(target, target_group, depes, command, separator)
*
* Take one target and a list of dependencies and process the whole thing.
* The target might be special in some sense in which case that is handled
*
* Parameters:
* target The target we want to enter
* target_group Non-NULL if target is part of a group this time
* depes A list of dependencies for the target
* command The command the target should be entered with
* separator Indicates if this is a ":" or a "::" rule
*
* Static variables used:
* built_last_make_run_seen If the previous target was
* .BUILT_LAST_MAKE_RUN we say to rewrite
* the state file later on
*
* Global variables used:
* command_changed Set to indicate if .make.state needs rewriting
* default_target_to_build Set to the target if reading makefile
* and this is the first regular target
* force The Name " FORCE", used with "::" targets
* makefile_type We do different things for makefile vs. report
* not_auto The Name ".NOT_AUTO", compared against
* recursive_name The Name ".RECURSIVE", compared against
* temp_file_number Used to figure out when to clear stale
* automatic dependencies
* trace_reader Indicates that we should echo stuff we read
*/
void
enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator)
{
register int i;
wchar_t *namep;
char *mb_namep;
register int recursive_state;
char *slash;
/* Check if this is a .RECURSIVE line */
target->has_recursive_dependency = true;
recursive_state = 0;
/* Read the dependencies. They are "<directory> <target-made>*/
/* <makefile>*" */
switch (recursive_state++) {
case 0: /* Directory */
{
relative);
}
break;
case 1: /* Target */
break;
default: /* Makefiles */
break;
}
}
}
}
/* Check if this recursion already has been reported else */
/* enter the recursive prop for the target */
/* The has_built flag is used to tell if this .RECURSIVE */
/* was discovered from this run (read from a tmp file) */
/* or was from discovered from the original .make.state */
/* file */
(Boolean)
return;
}
}
return;
}
/* If this is the first target that doesnt start with a "." in the */
/* makefile we remember that */
if ((makefile_type == reading_makefile) &&
(default_target_to_build == NULL) &&
((wcb[0] != (int) period_char) ||
/* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO):
** The target with empty name cannot be default_target_to_build
*/
}
/* Check if the line is ":" or "::" */
if (makefile_type == reading_makefile) {
} else {
}
}
/* If this is a "::" type line with no */
/* dependencies we add one "FRC" type */
/* dependency for free */
* depes to always run */
}
/* Do not delete "::" type targets when interrupted */
/*
* Build a synthetic target "<number>%target"
* for "target".
*/
"%d@%s",
target->colon_splits++,
} else {
*slash = 0;
"%s/%d@%s",
target->colon_splits++,
slash + 1);
*slash = (int) slash_char;
}
if (trace_reader) {
}
/* Make "target" depend on "<number>%target */
/* Put a prop on "<number>%target that makes */
/* appear as "target" */
/* when it is processed */
target->is_double_colon_parent = true;
name->is_double_colon = true;
name->has_target_prop = true;
if (trace_reader) {
(void) printf("\n");
}
}
}
/* This really is a regular dependency line. Just enter it */
/* Depending on what kind of makefile we are reading we have to */
/* treat things differently */
switch (makefile_type) {
case reading_makefile:
/* Reading regular makefile. Just notice whether this */
/* redefines the rule for the target */
true;
if ((wcb[0] == (int) period_char) &&
}
} else {
}
} else {
if ((wcb[0] == (int) period_char) &&
}
}
break;
case rereading_statefile:
/* Rereading the statefile. We only enter thing that changed */
/* since the previous time we read it */
if (!built_last_make_run_seen) {
}
return;
}
built_last_make_run_seen = false;
command_changed = true;
target->ran_command = true;
case reading_statefile:
/* Reading the statefile for the first time. Enter the rules */
/* as "Commands used" not "templates to use" */
}
}
case reading_cpp_file:
/* Reading report file from programs that reports */
/* dependencies. If this is the first time the target is */
/* read from this reportfile we clear all old */
/* automatic depes */
break;
}
command_changed = true;
}
}
}
break;
default:
}
/* A target may only be involved in one target group */
if (target_group != NULL) {
}
} else {
}
if (trace_reader) {
}
/* Enter the dependencies */
not_auto_found = false;
for (;
/* the dependency .NOT_AUTO signals beginning of
* explicit dependancies which were put at end of
* list in .make.state file - we stop entering
* dependencies at this point
*/
not_auto_found = true;
break;
}
}
}
if (trace_reader) {
(void) printf("\n");
}
}
/*
* enter_dependency(line, depe, automatic)
*
* Enter one dependency. Do not enter duplicates.
*
* Parameters:
* line The line block that the dependeny is
* entered for
* depe The dependency to enter
* automatic Used to set the field "automatic"
*
* Global variables used:
* makefile_type We do different things for makefile vs. report
* trace_reader Indicates that we should echo stuff we read
* wait_name The Name ".WAIT", compared against
*/
void
{
if (trace_reader) {
}
/* Find the end of the list and check for duplicates */
if (automatic) {
}
}
return;
}
}
/* Insert the new dependency since we couldnt find it */
if ((makefile_type == reading_makefile) &&
}
}
/*
* enter_percent(target, depes, command)
*
* Enter "x%y : a%b" type lines
* % patterns are stored in four parts head and tail for target and source
*
* Parameters:
* target Left hand side of pattern
* depes The dependency list with the rh pattern
* command The command for the pattern
*
* Global variables used:
* empty_name The Name "", compared against
* percent_list The list of all percent rules, added to
* trace_reader Indicates that we should echo stuff we read
*/
enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command)
{
int i;
int pattern;
result->patterns_total = 0;
result->being_expanded = false;
/* get patterns count */
while (true) {
result->patterns_total++;
cp++;
} else {
break;
}
}
result->patterns_total++;
/* allocate storage for patterns */
/* then create patterns */
pattern = 0;
while (true) {
pattern++;
} else {
break;
}
}
/* build dependencies list */
depe->patterns_total = 0;
depe->being_expanded = false;
/* get patterns count */
while (true) {
depe->patterns_total++;
cp++;
} else {
break;
}
}
depe->patterns_total++;
/* allocate storage for patterns */
/* then create patterns */
pattern = 0;
while (true) {
pattern++;
} else {
break;
}
}
}
}
}
/* Find the end of the percent list and append the new pattern */
if (trace_reader) {
}
(void) printf("\n");
}
return result;
}
/*
* enter_dyntarget(target)
*
* Enter "$$(MACRO) : b" type lines
*
* Parameters:
* target Left hand side of pattern
*
* Global variables used:
* dyntarget_list The list of all percent rules, added to
* trace_reader Indicates that we should echo stuff we read
*/
{
Dyntarget p;
int i;
/* Find the end of the dyntarget list and append the new pattern */
p != NULL;
if (trace_reader) {
}
return( result);
}
/*
* special_reader(target, depes, command)
*
* Read the pseudo targets make knows about
* This handles the special targets that should not be entered as regular
* target/dependency sets.
*
* Parameters:
* target The special target
* depes The list of dependencies it was entered with
* command The command it was entered with
*
* Static variables used:
* built_last_make_run_seen Set to indicate .BUILT_LAST... seen
*
* Global variables used:
* all_parallel Set to indicate that everything runs parallel
* svr4 Set when ".SVR4" target is read
* svr4_name The Name ".SVR4"
* posix Set when ".POSIX" target is read
* posix_name The Name ".POSIX"
* current_make_version The Name "<current version number>"
* default_rule Set when ".DEFAULT" target is read
* default_rule_name The Name ".DEFAULT", used for tracing
* dot_keep_state The Name ".KEEP_STATE", used for tracing
* ignore_errors Set if ".IGNORE" target is read
* ignore_name The Name ".IGNORE", used for tracing
* keep_state Set if ".KEEP_STATE" target is read
* no_parallel_name The Name ".NO_PARALLEL", used for tracing
* only_parallel Set to indicate only some targets runs parallel
* parallel_name The Name ".PARALLEL", used for tracing
* precious The Name ".PRECIOUS", used for tracing
* sccs_get_name The Name ".SCCS_GET", used for tracing
* sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing
* get_name The Name ".GET", used for tracing
* sccs_get_rule Set when ".SCCS_GET" target is read
* silent Set when ".SILENT" target is read
* silent_name The Name ".SILENT", used for tracing
* trace_reader Indicates that we should echo stuff we read
*/
void
{
register int n;
switch (target->special_reader) {
case svr4_special:
}
svr4 = true;
posix = false;
keep_state = false;
all_parallel = false;
only_parallel = false;
if (trace_reader) {
}
break;
case posix_special:
if(svr4)
break;
}
posix = true;
/* with posix on, use the posix get rule */
/* turn keep state off being SunPro make specific */
keep_state = false;
if (trace_reader) {
}
break;
built_last_make_run_seen = true;
break;
case default_special:
}
if (trace_reader) {
(void) printf("%s:\n",
}
break;
case ignore_special:
}
{
ignore_errors_all = true;
}
if(svr4) {
ignore_errors_all = true;
break;
}
}
}
if (trace_reader) {
}
break;
case keep_state_special:
if(svr4)
break;
/* ignore keep state, being SunPro make specific */
if(posix)
break;
}
keep_state = true;
if (trace_reader) {
(void) printf("%s:\n",
}
break;
case keep_state_file_special:
if(svr4)
break;
if(posix)
break;
/* it's not necessary to specify KEEP_STATE, if this
** is given, so set the keep_state.
*/
keep_state = true;
}
}
break;
case make_version_special:
if(svr4)
break;
}
/*
* Special case the fact that version 1.0 and 1.1
* are identical.
*/
"VERSION-1.1") ||
"VERSION-1.0")) {
/*
* Version mismatches should cause the
* .make.state file to be skipped.
* This is currently not true - it is read
* anyway.
*/
}
}
break;
case no_parallel_special:
if(svr4)
break;
/* Set the no_parallel bit for all the targets on */
/* the dependency list */
/* only those explicitly made parallel */
only_parallel = true;
all_parallel = false;
}
if (trace_reader) {
(void) printf("%s:\t%s\n",
}
}
}
break;
case parallel_special:
if(svr4)
break;
/* everything runs in parallel */
all_parallel = true;
only_parallel = false;
}
/* Set the parallel bit for all the targets on */
/* the dependency list */
if (trace_reader) {
(void) printf("%s:\t%s\n",
}
}
}
break;
case localhost_special:
if(svr4)
break;
/* Set the no_parallel bit for all the targets on */
/* the dependency list */
/* only those explicitly made parallel */
only_parallel = true;
all_parallel = false;
}
if (trace_reader) {
(void) printf("%s:\t%s\n",
}
}
}
break;
case precious_special:
/* everything is precious */
all_precious = true;
} else {
all_precious = false;
}
if(svr4) {
all_precious = true;
break;
}
/* Set the precious bit for all the targets on */
/* the dependency list */
if (trace_reader) {
(void) printf("%s:\t%s\n",
}
}
}
break;
case sccs_get_special:
}
if (trace_reader) {
}
break;
case sccs_get_posix_special:
}
if (trace_reader) {
}
break;
case get_posix_special:
}
if (trace_reader) {
}
break;
case get_special:
if(!svr4) {
break;
}
}
if (trace_reader) {
}
break;
case silent_special:
}
{
silent_all = true;
}
if(svr4) {
silent_all = true;
break;
}
}
}
if (trace_reader) {
}
break;
case suffixes_special:
break;
default:
}
}
/*
* read_suffixes_list(depes)
*
* Read the special list .SUFFIXES. If it is empty the old list is
* cleared. Else the new one is appended. Suffixes with ~ are extracted
* and marked.
*
* Parameters:
* depes The list of suffixes
*
* Global variables used:
* hashtab The central hashtable for Names.
* suffixes The list of suffixes, set or appended to
* suffixes_name The Name ".SUFFIXES", used for tracing
* trace_reader Indicates that we should echo stuff we read
*/
static void
{
register int n;
/* .SUFFIXES with no dependency list clears the */
/* suffixes list */
np->with_squiggle =
false;
}
if (trace_reader) {
}
return;
}
/* Otherwise we append to the list */
/* Find the end of the list and check if the */
/* suffix already has been entered */
goto duplicate_suffix;
}
}
if (trace_reader) {
if (first) {
(void) printf("%s:\t",
first = false;
}
}
/* If the suffix is suffixed with "~" we */
/* strip that and mark the suffix nameblock */
(int) tilde_char) {
np2->with_squiggle = true;
if (np2->without_squiggle) {
continue;
}
}
}
np->without_squiggle = true;
/* Add the suffix to the list */
}
}
if (trace_reader) {
(void) printf("\n");
}
}
/*
* make_relative(to, result)
*
* Given a file name compose a relative path name from it to the
* current directory.
*
* Parameters:
* to The path we want to make relative
* result Where to put the resulting relative path
*
* Global variables used:
*/
static void
{
wchar_t *from;
wchar_t *allocated;
wchar_t *cp;
wchar_t *tocomp;
int ncomps;
int i;
int len;
/* Check if the path is already relative. */
if (to[0] != (int) slash_char) {
return;
}
/*
* Find the number of components in the from name.
* ncomp = number of slashes + 1.
*/
ncomps = 1;
if (*cp == (int) slash_char) {
ncomps++;
}
}
/*
* See how many components match to determine how many "..",
* if any, will be needed.
*/
if (*from == (int) slash_char) {
ncomps--;
}
from++;
to++;
}
/*
* Now for some special cases. Check for exact matches and
* for either name terminating exactly.
*/
return;
}
if (*to == (int) slash_char) {
ncomps--;
}
ncomps--;
}
/* Add on the ".."s. */
for (i = 0; i < ncomps; i++) {
}
/* Add on the remainder of the to name, if any. */
} else {
}
return;
}
/*
* print_rule(command)
*
* Used when tracing the reading of rules
*
* Parameters:
* command Command to print
*
* Global variables used:
*/
static void
{
}
}
/*
* enter_conditional(target, name, value, append)
*
* Enter "target := MACRO= value" constructs
*
* Parameters:
* target The target the macro is for
* name The name of the macro
* value The value for the macro
* append Indicates if the assignment is appending or not
*
* Global variables used:
* conditionals A special Name that stores all conditionals
* where the target is a % pattern
* trace_reader Indicates that we should echo stuff we read
*/
void
{
static int sequence;
if (name == target_arch) {
}
}
}
/* Count how many conditionals we must activate before building the */
/* target */
}
/* Add the property for the target */
if (trace_reader) {
(void) printf("%s := %s %c=\n",
append ?
(int) plus_char : (int) space_char);
} else {
(void) printf("%s := %s %c= %s\n",
append ?
(int) plus_char : (int) space_char,
}
}
}
/*
* enter_equal(name, value, append)
*
* Enter "MACRO= value" constructs
*
* Parameters:
* name The name of the macro
* value The value for the macro
* append Indicates if the assignment is appending or not
*
* Global variables used:
* trace_reader Indicates that we should echo stuff we read
*/
void
{
wchar_t *string;
}
/* if we're setting FC, we want to set F77 to the same value. */
if (string[0]=='F' &&
/*
fprintf(stderr, gettext("warning: FC is obsolete, use F77 instead\n"));
*/
}
if (trace_reader) {
(void) printf("%s %c=\n",
append ?
(int) plus_char : (int) space_char);
} else {
(void) printf("%s %c= %s\n",
append ?
(int) plus_char : (int) space_char,
}
}
}
/*
* sh_transform(name, value)
*
* Parameters:
* name The name of the macro we might transform
* value The value to transform
*
*/
static void
{
/* Check if we need :sh transform */
wchar_t *colon;
}
buffer[0] = 0;
} else {
} else {
}
}
*colon = (int) colon_char;
}
}
/*
* fatal_reader(format, args...)
*
* Parameters:
* format printf style format string
* args arguments to match the format
*
* Global variables used:
* file_being_read Name of the makefile being read
* line_number Line that is being read
* report_pwd Indicates whether current path should be shown
* temp_file_name When reading tempfile we report that name
*/
/*VARARGS*/
void
{
if (file_being_read != NULL) {
if (line_number != 0) {
gettext("%s, line %d: %s"),
pattern);
} else {
"%s: %s",
pattern);
}
}
getprogname());
if (temp_file_name != NULL) {
gettext("%s: Temp-file %s not removed\n"),
getprogname(),
}
if (report_pwd) {
gettext("Current working directory %s\n"),
get_current_path());
}
exit_status = 1;
exit(1);
}