- Move -D flags from Makefile to config.h and explain what they do. Add

-Wall -Wno-unused to CFLAGS. Add new define SYSVVARSUB to enable SysV
  style variable substitutions and enable them.
- Add SunOS style command substitutions via SUNSHCMD
- Fix core dump with '{variable = value'
This commit is contained in:
christos 1996-05-28 23:34:35 +00:00
parent ecbb3b2eb2
commit 5c1983c016
6 changed files with 240 additions and 159 deletions

View File

@ -1,8 +1,8 @@
# $NetBSD: Makefile,v 1.10 1996/03/11 13:45:31 christos Exp $
# $NetBSD: Makefile,v 1.11 1996/05/28 23:34:35 christos Exp $
# @(#)Makefile 5.2 (Berkeley) 12/28/90
PROG= make
CFLAGS+= -I${.CURDIR} -DPOSIX -DSYSVINCLUDE
CFLAGS+= -I${.CURDIR} -Wall -Wno-unused
SRCS= arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c main.c \
make.c parse.c str.c suff.c targ.c var.c util.c
SRCS+= lstAppend.c lstAtEnd.c lstAtFront.c lstClose.c lstConcat.c \

View File

@ -1,4 +1,4 @@
/* $NetBSD: config.h,v 1.5 1996/02/04 20:34:43 christos Exp $ */
/* $NetBSD: config.h,v 1.6 1996/05/28 23:34:39 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -80,14 +80,37 @@
* re-made, causing later targets to appear up-to-date. On systems
* that don't have this problem, you should defined this. Under
* NFS you probably should not, unless you aren't exporting jobs.
*
* POSIX
* If the POSIX standard for Make is to be followed. There are
* several areas that I dislike, hence this constant.
*/
#define LIBSUFF ".a"
#define RECHECK
/*
* POSIX
* Adhere to the POSIX 1003.2 draft for the make(1) program.
* - Use MAKEFLAGS instead of MAKE to pick arguments from the
* environment.
* - Allow empty command lines if starting with tab.
*/
#define POSIX
/*
* SYSVINCLUDES
* Recognize system V like include directives [include "filename"]
* SYSVVARSUB
* Recognize system V like ${VAR:x=y} variable substitutions
*/
#define SYSVINCLUDES
#define SYSVVARSUB
/*
* SUNSHCMD
* Recognize SunOS and Solaris:
* VAR :sh= CMD # Assign VAR to the command substitution of CMD
* ${VAR:sh} # Return the command substitution of the value
* # of ${VAR}
*/
#define SUNSHCMD
#if !defined(__svr4__) && !defined(__SVR4)
# ifndef RANLIBMAG
# define RANLIBMAG "__.SYMDEF"

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.28 1996/03/31 21:30:05 christos Exp $ */
/* $NetBSD: main.c,v 1.29 1996/05/28 23:34:41 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -48,7 +48,7 @@ char copyright[] =
#if 0
static char sccsid[] = "@(#)main.c 5.25 (Berkeley) 4/1/91";
#else
static char rcsid[] = "$NetBSD: main.c,v 1.28 1996/03/31 21:30:05 christos Exp $";
static char rcsid[] = "$NetBSD: main.c,v 1.29 1996/05/28 23:34:41 christos Exp $";
#endif
#endif /* not lint */
@ -86,6 +86,7 @@ static char rcsid[] = "$NetBSD: main.c,v 1.28 1996/03/31 21:30:05 christos Exp $
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@ -819,6 +820,142 @@ found: Var_Set("MAKEFILE", fname, VAR_GLOBAL);
return(TRUE);
}
/*-
* Cmd_Exec --
* Execute the command in cmd, and return the output of that command
* in a string.
*
* Results:
* A string containing the output of the command, or the empty string
* If err is not NULL, it contains the reason for the command failure
*
* Side Effects:
* The string must be freed by the caller.
*/
char *
Cmd_Exec(cmd, err)
char *cmd;
char **err;
{
char *args[4]; /* Args for invoking the shell */
int fds[2]; /* Pipe streams */
int cpid; /* Child PID */
int pid; /* PID from wait() */
char *res; /* result */
int status; /* command exit status */
Buffer buf; /* buffer to store the result */
char *cp;
int cc;
*err = NULL;
/*
* Set up arguments for shell
*/
args[0] = "sh";
args[1] = "-c";
args[2] = cmd;
args[3] = NULL;
/*
* Open a pipe for fetching its output
*/
if (pipe(fds) == -1) {
*err = "Couldn't create pipe for \"%s\"";
goto bad;
}
/*
* Fork
*/
switch (cpid = vfork()) {
case 0:
/*
* Close input side of pipe
*/
(void) close(fds[0]);
/*
* Duplicate the output stream to the shell's output, then
* shut the extra thing down. Note we don't fetch the error
* stream...why not? Why?
*/
(void) dup2(fds[1], 1);
(void) close(fds[1]);
(void) execv("/bin/sh", args);
_exit(1);
/*NOTREACHED*/
case -1:
*err = "Couldn't exec \"%s\"";
goto bad;
default:
/*
* No need for the writing half
*/
(void) close(fds[1]);
buf = Buf_Init (MAKE_BSIZE);
do {
char result[BUFSIZ];
cc = read(fds[0], result, sizeof(result));
if (cc > 0)
Buf_AddBytes(buf, cc, (Byte *) result);
}
while (cc > 0 || (cc == -1 && errno == EINTR));
/*
* Close the input side of the pipe.
*/
(void) close(fds[0]);
/*
* Wait for the process to exit.
*/
while(((pid = wait(&status)) != cpid) && (pid >= 0))
continue;
res = (char *)Buf_GetAll (buf, &cc);
Buf_Destroy (buf, FALSE);
if (cc == 0)
*err = "Couldn't read shell's output for \"%s\"";
if (status)
*err = "\"%s\" returned non-zero status";
/*
* Null-terminate the result, convert newlines to spaces and
* install it in the variable.
*/
res[cc] = '\0';
cp = &res[cc] - 1;
if (*cp == '\n') {
/*
* A final newline is just stripped
*/
*cp-- = '\0';
}
while (cp >= res) {
if (*cp == '\n') {
*cp = ' ';
}
cp--;
}
break;
}
return res;
bad:
res = emalloc(1);
*res = '\0';
return res;
}
/*-
* Error --
* Print an error message given its format.

View File

@ -1,4 +1,4 @@
/* $NetBSD: nonints.h,v 1.9 1996/03/31 21:30:07 christos Exp $ */
/* $NetBSD: nonints.h,v 1.10 1996/05/28 23:34:44 christos Exp $ */
/*-
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -65,6 +65,7 @@ void For_Run __P((void));
/* main.c */
void Main_ParseArgLine __P((char *));
int main __P((int, char **));
char *Cmd_Exec __P((char *, char **));
void Error __P((char *, ...));
void Fatal __P((char *, ...));
void Punt __P((char *, ...));

View File

@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.22 1996/03/15 21:52:41 christos Exp $ */
/* $NetBSD: parse.c,v 1.23 1996/05/28 23:34:46 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)parse.c 5.18 (Berkeley) 2/19/91";
#else
static char rcsid[] = "$NetBSD: parse.c,v 1.22 1996/03/15 21:52:41 christos Exp $";
static char rcsid[] = "$NetBSD: parse.c,v 1.23 1996/05/28 23:34:46 christos Exp $";
#endif
#endif /* not lint */
@ -96,7 +96,6 @@ static char rcsid[] = "$NetBSD: parse.c,v 1.22 1996/03/15 21:52:41 christos Exp
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <sys/wait.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
@ -1275,22 +1274,31 @@ Parse_IsVar (line)
default:
if (wasSpace && haveName) {
if (ISEQOPERATOR(*line)) {
/*
* We must have a finished word
*/
if (level != 0)
return FALSE;
/*
* When an = operator [+?!:] is found, the next
* character * must be an = or it ain't a valid
* character must be an = or it ain't a valid
* assignment.
*/
if (line[1] != '=' && level == 0)
return FALSE;
else
if (line[1] == '=')
return haveName;
}
else {
#ifdef SUNSHCMD
/*
* This is the start of another word, so not assignment.
* This is a shell command
*/
return FALSE;
if (strncmp(line, ":sh", 3) == 0)
return haveName;
#endif
}
/*
* This is the start of another word, so not assignment.
*/
return FALSE;
}
else {
haveName = TRUE;
@ -1393,6 +1401,17 @@ Parse_DoVar (line, ctxt)
break;
default:
#ifdef SUNSHCMD
while (*opc != ':')
if (--opc < line)
break;
if (strncmp(opc, ":sh", 3) == 0) {
type = VAR_SHELL;
*opc = '\0';
break;
}
#endif
type = VAR_NORMAL;
break;
}
@ -1424,156 +1443,38 @@ Parse_DoVar (line, ctxt)
Var_Set(line, cp, ctxt);
free(cp);
} else if (type == VAR_SHELL) {
char *args[4]; /* Args for invoking the shell */
int fds[2]; /* Pipe streams */
int cpid; /* Child PID */
int pid; /* PID from wait() */
Boolean freeCmd; /* TRUE if the command needs to be freed, i.e.
* if any variable expansion was performed */
Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
* if any variable expansion was performed */
char *res, *err;
/*
* Avoid clobbered variable warnings by forcing the compiler
* to ``unregister'' variables
*/
#if __GNUC__
(void) &freeCmd;
#endif
/*
* Set up arguments for shell
*/
args[0] = "sh";
args[1] = "-c";
if (strchr(cp, '$') != (char *)NULL) {
if (strchr(cp, '$') != NULL) {
/*
* There's a dollar sign in the command, so perform variable
* expansion on the whole thing. The resulting string will need
* freeing when we're done, so set freeCmd to TRUE.
*/
args[2] = Var_Subst(NULL, cp, VAR_CMD, TRUE);
cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
freeCmd = TRUE;
} else {
args[2] = cp;
freeCmd = FALSE;
}
args[3] = (char *)NULL;
/*
* Open a pipe for fetching its output
*/
pipe(fds);
res = Cmd_Exec(cp, &err);
Var_Set(line, res, ctxt);
free(res);
/*
* Fork
*/
cpid = vfork();
if (cpid == 0) {
/*
* Close input side of pipe
*/
close(fds[0]);
if (err)
Parse_Error(PARSE_WARNING, err, cp);
/*
* Duplicate the output stream to the shell's output, then
* shut the extra thing down. Note we don't fetch the error
* stream...why not? Why?
*/
dup2(fds[1], 1);
close(fds[1]);
execv("/bin/sh", args);
_exit(1);
} else if (cpid < 0) {
/*
* Couldn't fork -- tell the user and make the variable null
*/
Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp);
Var_Set(line, "", ctxt);
} else {
int status;
int cc;
Buffer buf;
char *res;
/*
* No need for the writing half
*/
close(fds[1]);
buf = Buf_Init (MAKE_BSIZE);
do {
char result[BUFSIZ];
cc = read(fds[0], result, sizeof(result));
if (cc > 0)
Buf_AddBytes(buf, cc, (Byte *) result);
}
while (cc > 0 || (cc == -1 && errno == EINTR));
/*
* Close the input side of the pipe.
*/
close(fds[0]);
/*
* Wait for the process to exit.
*/
while(((pid = wait(&status)) != cpid) && (pid >= 0))
continue;
res = (char *)Buf_GetAll (buf, &cc);
Buf_Destroy (buf, FALSE);
if (cc == 0) {
/*
* Couldn't read the child's output -- tell the user and
* set the variable to null
*/
Parse_Error(PARSE_WARNING, "Couldn't read shell's output");
}
if (status) {
/*
* Child returned an error -- tell the user but still use
* the result.
*/
Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
}
/*
* Null-terminate the result, convert newlines to spaces and
* install it in the variable.
*/
res[cc] = '\0';
cp = &res[cc] - 1;
if (*cp == '\n') {
/*
* A final newline is just stripped
*/
*cp-- = '\0';
}
while (cp >= res) {
if (*cp == '\n') {
*cp = ' ';
}
cp--;
}
Var_Set(line, res, ctxt);
free(res);
}
if (freeCmd) {
free(args[2]);
}
if (freeCmd)
free(cp);
} else {
/*
* Normal assignment -- just do it.
*/
Var_Set (line, cp, ctxt);
Var_Set(line, cp, ctxt);
}
}
/*-
* ParseAddCmd --
* Lst_ForEach function to add a command line to all targets

View File

@ -1,4 +1,4 @@
/* $NetBSD: var.c,v 1.12 1995/11/02 23:55:12 christos Exp $ */
/* $NetBSD: var.c,v 1.13 1996/05/28 23:34:49 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)var.c 5.7 (Berkeley) 6/1/90";
#else
static char rcsid[] = "$NetBSD: var.c,v 1.12 1995/11/02 23:55:12 christos Exp $";
static char rcsid[] = "$NetBSD: var.c,v 1.13 1996/05/28 23:34:49 christos Exp $";
#endif
#endif /* not lint */
@ -165,7 +165,9 @@ static Boolean VarTail __P((char *, Boolean, Buffer, ClientData));
static Boolean VarSuffix __P((char *, Boolean, Buffer, ClientData));
static Boolean VarRoot __P((char *, Boolean, Buffer, ClientData));
static Boolean VarMatch __P((char *, Boolean, Buffer, ClientData));
#ifdef SYSVVARSUB
static Boolean VarSYSVMatch __P((char *, Boolean, Buffer, ClientData));
#endif
static Boolean VarNoMatch __P((char *, Boolean, Buffer, ClientData));
static Boolean VarSubstitute __P((char *, Boolean, Buffer, ClientData));
static char *VarModify __P((char *, Boolean (*)(char *, Boolean, Buffer,
@ -782,8 +784,7 @@ VarMatch (word, addSpace, buf, pattern)
return(addSpace);
}
#ifdef SYSVVARSUB
/*-
*-----------------------------------------------------------------------
* VarSYSVMatch --
@ -825,6 +826,7 @@ VarSYSVMatch (word, addSpace, buf, patp)
return(addSpace);
}
#endif
/*-
@ -1633,7 +1635,22 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
break;
}
/*FALLTHRU*/
default: {
#ifdef SUNSHCMD
case 's':
if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
char *err;
newStr = Cmd_Exec (str, &err);
if (err)
Error (err, str);
cp = tstr + 2;
termc = *cp;
break;
}
/*FALLTHRU*/
#endif
default:
{
#ifdef SYSVVARSUB
/*
* This can either be a bogus modifier or a System-V
* substitution command.
@ -1700,7 +1717,9 @@ Var_Parse (str, ctxt, err, lengthPtr, freePtr)
pattern.lhs[pattern.leftLen] = '=';
pattern.rhs[pattern.rightLen] = endc;
termc = endc;
} else {
} else
#endif
{
Error ("Unknown modifier '%c'\n", *tstr);
for (cp = tstr+1;
*cp != ':' && *cp != endc && *cp != '\0';