home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 5
/
FreshFish_July-August1994.bin
/
bbs
/
gnu
/
make-3.71-src.lha
/
src
/
amiga
/
make-3.71
/
read.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-22
|
54KB
|
2,039 lines
/* Reading and parsing of makefiles for GNU Make.
Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Make is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Make; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "make.h"
#include "commands.h"
#include "dep.h"
#include "file.h"
#include "variable.h"
/* This is POSIX.2, but most systems using -DPOSIX probably don't have it. */
#ifdef HAVE_GLOB_H
#include <glob.h>
#else
#include "glob/glob.h"
#endif
#include <pwd.h>
struct passwd *getpwnam ();
static int read_makefile ();
static unsigned int readline (), do_define ();
static int conditional_line ();
static void record_files ();
static char *find_semicolon ();
/* A `struct linebuffer' is a structure which holds a line of text.
`readline' reads a line from a stream into a linebuffer
and works regardless of the length of the line. */
struct linebuffer
{
/* Note: This is the number of bytes malloc'ed for `buffer'
It does not indicate `buffer's real length.
Instead, a null char indicates end-of-string. */
unsigned int size;
char *buffer;
};
#define initbuffer(lb) (lb)->buffer = (char *) xmalloc ((lb)->size = 200)
#define freebuffer(lb) free ((lb)->buffer)
/* A `struct conditionals' contains the information describing
all the active conditionals in a makefile.
The global variable `conditionals' contains the conditionals
information for the current makefile. It is initialized from
the static structure `toplevel_conditionals' and is later changed
to new structures for included makefiles. */
struct conditionals
{
unsigned int if_cmds; /* Depth of conditional nesting. */
unsigned int allocated; /* Elts allocated in following arrays. */
char *ignoring; /* Are we ignoring or interepreting? */
char *seen_else; /* Have we already seen an `else'? */
};
static struct conditionals toplevel_conditionals;
static struct conditionals *conditionals = &toplevel_conditionals;
/* Default directories to search for include files in */
static char *default_include_directories[] =
{
#ifndef amigados
INCLUDEDIR,
"/usr/gnu/include",
"/usr/local/include",
"/usr/include",
#else
"/gnu/include",
"/gnu/g++-include",
"/gnu/os-include",
"/local/include",
"/local/g++-include",
"/local/os-include",
#endif
0
};
/* List of directories to search for include files in */
static char **include_directories;
/* Maximum length of an element of the above. */
static unsigned int max_incl_len;
/* The filename and pointer to line number of the
makefile currently being read in. */
char *reading_filename;
unsigned int *reading_lineno_ptr;
/* The chain of makefiles read by read_makefile. */
static struct dep *read_makefiles = 0;
/* Read in all the makefiles and return the chain of their names. */
struct dep *
read_all_makefiles (makefiles)
char **makefiles;
{
unsigned int num_makefiles = 0;
if (debug_flag)
puts ("Reading makefiles...");
/* If there's a non-null variable MAKEFILES, its value is a list of
files to read first thing. But don't let it prevent reading the
default makefiles and don't let the default goal come from there. */
{
char *value;
char *name, *p;
unsigned int length;
{
/* Turn off --warn-undefined-variables while we expand MAKEFILES. */
int save = warn_undefined_variables_flag;
warn_undefined_variables_flag = 0;
value = allocated_variable_expand ("$(MAKEFILES)");
warn_undefined_variables_flag = save;
}
/* Set NAME to the start of next token and LENGTH to its length.
MAKEFILES is updated for finding remaining tokens. */
p = value;
while ((name = find_next_token (&p, &length)) != 0)
{
if (*p != '\0')
*p++ = '\0';
(void) read_makefile (name,
RM_NO_DEFAULT_GOAL | RM_INCLUDED | RM_DONTCARE);
}
free (value);
}
/* Read makefiles specified with -f switches. */
if (makefiles != 0)
while (*makefiles != 0)
{
struct dep *tail = read_makefiles;
register struct dep *d;
if (! read_makefile (*makefiles, 0))
perror_with_name ("", *makefiles);
/* Find the right element of read_makefiles. */
d = read_makefiles;
while (d->next != tail)
d = d->next;
/* Use the storage read_makefile allocates. */
*makefiles = dep_name (d);
++num_makefiles;
++makefiles;
}
/* If there were no -f switches, try the default names. */
if (num_makefiles == 0)
{
static char *default_makefiles[] =
{ "GNUmakefile", "makefile", "Makefile", 0 };
register char **p = default_makefiles;
while (*p != 0 && !file_exists_p (*p))
++p;
if (*p != 0)
{
if (! read_makefile (*p, 0))
perror_with_name ("", *p);
}
else
{
/* No default makefile was found. Add the default makefiles to the
`read_makefiles' chain so they will be updated if possible. */
struct dep *tail = read_makefiles;
for (p = default_makefiles; *p != 0; ++p)
{
struct dep *d = (struct dep *) xmalloc (sizeof (struct dep));
d->name = 0;
d->file = enter_file (*p);
d->file->dontcare = 1;
/* Tell update_goal_chain to bail out as soon as this file is
made, and main not to die if we can't make this file. */
d->changed = RM_DONTCARE;
if (tail == 0)
read_makefiles = d;
else
tail->next = d;
tail = d;
}
if (tail != 0)
tail->next = 0;
}
}
return read_makefiles;
}
/* Read file FILENAME as a makefile and add its contents to the data base.
FLAGS contains bits as above.
FILENAME is added to the `read_makefiles' chain.
Returns 1 if a file was found and read, 0 if not. */
static int
read_makefile (filename, flags)
char *filename;
int flags;
{
static char *collapsed = 0;
static unsigned int collapsed_length = 0;
register FILE *infile;
struct linebuffer lb;
unsigned int commands_len = 200;
char *commands = (char *) xmalloc (200);
unsigned int commands_idx = 0;
unsigned int commands_started;
register char *p;
char *p2;
int ignoring = 0, in_ignored_define = 0;
int no_targets = 0; /* Set when reading a rule without targets. */
struct nameseq *filenames = 0;
struct dep *deps;
unsigned int lineno = 1;
unsigned int nlines = 0;
int two_colon;
char *pattern = 0, *pattern_percent;
int makefile_errno;
#define record_waiting_files() \
do \
{ \
if (filenames != 0) \
record_files (filenames, pattern, pattern_percent, deps, \
commands_started, commands, commands_idx, \
two_colon, filename, lineno, \
!(flags & RM_NO_DEFAULT_GOAL)); \
filenames = 0; \
commands_idx = 0; \
pattern = 0; \
} while (0)
#ifdef lint /* Suppress `used before set' messages. */
two_colon = 0;
#endif
if (debug_flag)
{
printf ("Reading makefile `%s'", filename);
if (flags & RM_NO_DEFAULT_GOAL)
printf (" (no default goal)");
if (flags & RM_INCLUDED)
printf (" (search path)");
if (flags & RM_DONTCARE)
printf (" (don't care)");
if (flags & RM_NO_TILDE)
printf (" (no ~ expansion)");
puts ("...");
}
/* First, get a stream to read. */
/* Expand ~ in FILENAME unless it came from `include',
in which case it was already done. */
if (!(flags & RM_NO_TILDE) && filename[0] == '~')
{
char *expanded = tilde_expand (filename)