783 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			783 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*************************************************************************
 | |
|  *
 | |
|  *  m a k e :   m a k e . c
 | |
|  *
 | |
|  *  Do the actual making for make plus system dependent stuff
 | |
|  *========================================================================
 | |
|  * Edition history
 | |
|  *
 | |
|  *  #    Date                         Comments                       By
 | |
|  * --- -------- ---------------------------------------------------- ---
 | |
|  *   1    ??                                                         ??
 | |
|  *   2 01.07.89 $<,$* bugs fixed                                     RAL
 | |
|  *   3 23.08.89 (time_t)time((time_t*)0) bug fixed, N_EXISTS added   RAL
 | |
|  *   4 30.08.89 leading sp. in cmd. output eliminated, indention ch. PSH,RAL
 | |
|  *   5 03.09.89 :: time fixed, error output -> stderr, N_ERROR intr.
 | |
|  *              fixed LZ elimintaed                                  RAL
 | |
|  *   6 07.09.89 implmacro, DF macros,debug stuff added               RAL
 | |
|  *   7 09.09.89 tos support added                                    PHH,RAL
 | |
|  *   8 17.09.89 make1 arg. fixed, N_EXEC introduced                  RAL
 | |
|  * ------------ Version 2.0 released ------------------------------- RAL
 | |
|  *     18.05.90 fixed -n bug with silent rules.  (Now echos them.)   PAN
 | |
|  *
 | |
|  *************************************************************************/
 | |
| 
 | |
| #include "h.h"
 | |
| #include <sys/wait.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| _PROTOTYPE(static void tellstatus, (FILE *out, char *name, int status));
 | |
| 
 | |
| static bool  execflag;
 | |
| 
 | |
| /*
 | |
|  *	Exec a shell that returns exit status correctly (/bin/esh).
 | |
|  *	The standard EON shell returns the process number of the last
 | |
|  *	async command, used by the debugger (ugg).
 | |
|  *	[exec on eon is like a fork+exec on unix]
 | |
|  */
 | |
| int dosh(string, shell)
 | |
| char *string;
 | |
| char *shell;
 | |
| {
 | |
|   int number;
 | |
| 
 | |
| #ifdef unix
 | |
|   return system(string);
 | |
| #endif
 | |
| #ifdef tos
 | |
|   return Tosexec(string);
 | |
| #endif
 | |
| #ifdef eon
 | |
|   return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
 | |
| 	-1:	/* couldn't start the shell */
 | |
| 	wait(number);	/* return its exit status */
 | |
| #endif
 | |
| #ifdef os9
 | |
|   int	status, pid;
 | |
| 
 | |
|   strcat(string, "\n");
 | |
|   if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
 | |
| 	return -1;		/* Couldn't start a shell */
 | |
|   do {
 | |
| 	if ((pid = wait(&status)) == -1)
 | |
| 		return -1;	/* child already died!?!? */
 | |
|   } while (pid != number);
 | |
| 
 | |
|   return status;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifdef unix
 | |
| /*
 | |
|  *    Make a file look very outdated after an error trying to make it.
 | |
|  *    Don't remove, this keeps hard links intact.  (kjb)
 | |
|  */
 | |
| int makeold(name) char *name;
 | |
| {
 | |
|   struct utimbuf a;
 | |
| 
 | |
|   a.actime = a.modtime = 0;	/* The epoch */
 | |
| 
 | |
|   return utime(name, &a);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static void tellstatus(out, name, status)
 | |
| FILE *out;
 | |
| char *name;
 | |
| int status;
 | |
| {
 | |
|   char cwd[PATH_MAX];
 | |
| 
 | |
|   fprintf(out, "%s in %s: ",
 | |
| 	name, getcwd(cwd, sizeof(cwd)) == NULL ? "?" : cwd);
 | |
| 
 | |
|   if (WIFEXITED(status)) {
 | |
| 	fprintf(out, "Exit code %d", WEXITSTATUS(status));
 | |
|   } else {
 | |
| 	fprintf(out, "Signal %d%s",
 | |
| 		WTERMSIG(status), status & 0x80 ? " - core dumped" : "");
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *	Do commands to make a target
 | |
|  */
 | |
| void docmds1(np, lp)
 | |
| struct name *np;
 | |
| struct line *lp;
 | |
| {
 | |
|   register char       *q;
 | |
|   register char       *p;
 | |
|   register struct cmd *cp;
 | |
|   bool                 ssilent;
 | |
|   bool                 signore;
 | |
|   int                  estat;
 | |
|   char                *shell;
 | |
| 
 | |
| 
 | |
|   if (*(shell = getmacro("SHELL")) == '\0')
 | |
| #ifdef eon
 | |
| 	shell = ":bin/esh";
 | |
| #endif
 | |
| #ifdef unix
 | |
| 	shell = "/bin/sh";
 | |
| #endif
 | |
| #ifdef os9
 | |
| 	shell = "shell";
 | |
| #endif
 | |
| #ifdef tos
 | |
| 	shell = "DESKTOP";      /* TOS has no shell */
 | |
| #endif
 | |
| 
 | |
|   for (cp = lp->l_cmd; cp; cp = cp->c_next) {
 | |
| 	execflag = TRUE;
 | |
| 	strcpy(str1, cp->c_cmd);
 | |
| 	expmake = FALSE;
 | |
| 	expand(&str1s);
 | |
| 	q = str1;
 | |
| 	ssilent = silent;
 | |
| 	signore = ignore;
 | |
| 	while ((*q == '@') || (*q == '-')) {
 | |
| 		if (*q == '@')	   /*  Specific silent  */
 | |
| 			ssilent = TRUE;
 | |
| 		else		   /*  Specific ignore  */
 | |
| 			signore = TRUE;
 | |
| 		if (!domake) putchar(*q);  /* Show all characters. */
 | |
| 		q++;		   /*  Not part of the command  */
 | |
| 	}
 | |
| 
 | |
| 	for (p=q; *p; p++) {
 | |
| 		if (*p == '\n' && p[1] != '\0') {
 | |
| 			*p = ' ';
 | |
| 			if (!ssilent || !domake)
 | |
| 				fputs("\\\n", stdout);
 | |
| 		}
 | |
| 		else if (!ssilent || !domake)
 | |
| 			putchar(*p);
 | |
| 	}
 | |
| 	if (!ssilent || !domake)
 | |
| 		putchar('\n');
 | |
| 
 | |
| 	if (domake || expmake) {	/*  Get the shell to execute it  */
 | |
| 		fflush(stdout);
 | |
| 		if ((estat = dosh(q, shell)) != 0) {
 | |
| 		    if (estat == -1)
 | |
| 			fatal("Couldn't execute %s", shell,0);
 | |
| 		    else if (signore) {
 | |
| 			tellstatus(stdout, myname, estat);
 | |
| 			printf(" (Ignored)\n");
 | |
| 		    } else {
 | |
| 			tellstatus(stderr, myname, estat);
 | |
| 			fprintf(stderr, "\n");
 | |
| 			if (!(np->n_flag & N_PREC))
 | |
| #ifdef unix
 | |
| 			    if (makeold(np->n_name) == 0)
 | |
| 				fprintf(stderr,"%s: made '%s' look old.\n", myname, np->n_name);
 | |
| #else
 | |
| 			    if (unlink(np->n_name) == 0)
 | |
| 				fprintf(stderr,"%s: '%s' removed.\n", myname, np->n_name);
 | |
| #endif
 | |
| 			if (!conterr) exit(estat != 0);
 | |
| 			np->n_flag |= N_ERROR;
 | |
| 			return;
 | |
| 		    }
 | |
| 		}
 | |
| 	}
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void docmds(np)
 | |
| struct name *np;
 | |
| {
 | |
|   register struct line *lp;
 | |
| 
 | |
|   for (lp = np->n_line; lp; lp = lp->l_next)
 | |
| 	docmds1(np, lp);
 | |
| }
 | |
| 
 | |
| #ifdef tos
 | |
| /*
 | |
|  *      execute the command submitted by make,
 | |
|  *      needed because TOS has no internal shell,
 | |
|  *      so we use Pexec to do the job
 | |
|  *        v 1.1 of 10/sep/89 by yeti
 | |
|  */
 | |
| 
 | |
| #define DELM1 ';'
 | |
| #define DELM2 ' '
 | |
| #define DELM3 ','
 | |
| 
 | |
| int Tosexec(string)
 | |
| char *string;
 | |
| {
 | |
|   register char *help, *help2, c;
 | |
|   register unsigned char l=1;
 | |
|   char progname[80], command[255], plain[15];
 | |
|   static char **envp,*env;
 | |
|   register int error,i;
 | |
| 
 | |
|   /* generate strange TOS environment (RAL) */
 | |
|   for ( i = 0, envp = environ; *envp; envp++) i += strlen(*envp) +1;
 | |
|   if ((env = malloc(i+1)) == (char *)0)
 | |
|      fatal("No memory for TOS environment",(char *)0,0);
 | |
|   for ( envp = environ, help = env; *envp; envp++) {
 | |
|      strcpy ( help, *envp);
 | |
|      while ( *(help++)) ;
 | |
|   }
 | |
|   *help = '\0';
 | |
| 
 | |
|   help = progname;
 | |
|   while((*help++=*string++) != ' '); /* progname is command name */
 | |
|   *--help = '\0';
 | |
| 
 | |
|   l = strlen(string);             /* build option list */
 | |
|   command[0] = l;                 /* TOS likes it complicated */
 | |
|   strcpy(&command[1],string);
 | |
|   if ((error = (int) Pexec(0,progname,command,env)) != -33) {
 | |
|     free(env);
 | |
|     return(error);
 | |
|   }
 | |
| 
 | |
|   /* could'nt find program, try to search the PATH */
 | |
|   if((help=strrchr(progname,'\\')) != (char *) 0)  /* just the */
 | |
|           strcpy(plain,++help);                     /* name     */
 | |
|   else if((help=strrchr(progname,'/')) != (char *) 0)
 | |
|           strcpy(plain,++help);
 | |
|   else if((help=strrchr(progname,':')) != (char *) 0)
 | |
|           strcpy(plain,++help);
 | |
|   else
 | |
|           strcpy(plain,progname);
 | |
| 
 | |
|   if(*(help=getmacro("PATH")) == '\0') {
 | |
|     free(env);
 | |
|     return(-33);
 | |
|   }
 | |
|   c = 1;
 | |
|   while(c)
 | |
|   {       help2 = &progname[-1];
 | |
|           i = 0;
 | |
|           while((c=*help++) != '\0' && i<80 && c != DELM1
 | |
|                  && c != DELM2 && c != DELM3)
 | |
|                   *++help2 = c, i++;
 | |
|           *++help2 = '\\';
 | |
|           strcpy(++help2,plain);
 | |
|           if((error=(int) Pexec(0,progname,command,env))!=-33) {
 | |
|                   free(env);
 | |
|                   return(error);
 | |
|           }
 | |
|   }
 | |
|   free(env);
 | |
|   return(-33);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* (stolen from ZOO -- thanks to Rahul Dehsi)
 | |
| Function mstonix() accepts an MSDOS format date and time and returns
 | |
| a **IX format time.  No adjustment is done for timezone.
 | |
| */
 | |
| 
 | |
| time_t mstonix (date, time)
 | |
| unsigned int date, time;
 | |
| {
 | |
|    int year, month, day, hour, min, sec, daycount;
 | |
|    time_t longtime;
 | |
|    /* no. of days to beginning of month for each month */
 | |
|    static int dsboy[12] = { 0, 31, 59, 90, 120, 151, 181, 212,
 | |
|                               243, 273, 304, 334};
 | |
| 
 | |
|    if (date == 0 && time == 0)			/* special case! */
 | |
|       return (0L);
 | |
| 
 | |
|    /* part of following code is common to zoolist.c */
 | |
|    year  =  (((unsigned int) date >> 9) & 0x7f) + 1980;
 | |
|    month =  ((unsigned int) date >> 5) & 0x0f;
 | |
|    day   =  date        & 0x1f;
 | |
| 
 | |
|    hour =  ((unsigned int) time >> 11)& 0x1f;
 | |
|    min   =  ((unsigned int) time >> 5) & 0x3f;
 | |
|    sec   =  ((unsigned int) time & 0x1f) * 2;
 | |
| 
 | |
| /* DEBUG and leap year fixes thanks to Mark Alexander <uunet!amdahl!drivax!alexande>*/
 | |
| #ifdef DEBUG
 | |
|    printf ("mstonix:  year=%d  month=%d  day=%d  hour=%d  min=%d  sec=%d\n",
 | |
|          year, month, day, hour, min, sec);
 | |
| #endif
 | |
|    /* Calculate days since 1970/01/01 */
 | |
|    daycount = 365 * (year - 1970) +    /* days due to whole years */
 | |
|                (year - 1969) / 4 +     /* days due to leap years */
 | |
|                dsboy[month-1] +        /* days since beginning of this year */
 | |
|                day-1;                  /* days since beginning of month */
 | |
| 
 | |
|    if (year % 4 == 0 &&
 | |
|        year % 400 != 0 && month >= 3)  /* if this is a leap year and month */
 | |
|       daycount++;                      /* is March or later, add a day */
 | |
| 
 | |
|    /* Knowing the days, we can find seconds */
 | |
|    longtime = daycount * 24L * 60L * 60L    +
 | |
|           hour * 60L * 60L   +   min * 60   +    sec;
 | |
| 	return (longtime);
 | |
| }
 | |
| #endif /* tos */
 | |
| 
 | |
| #ifdef os9
 | |
| /*
 | |
|  *	Some stuffing around to get the modified time of a file
 | |
|  *	in an os9 file system
 | |
|  */
 | |
| void getmdate(fd, tbp)
 | |
| int fd;
 | |
| struct sgtbuf *tbp;
 | |
| {
 | |
|   struct registers     regs;
 | |
|   static struct fildes fdbuf;
 | |
| 
 | |
| 
 | |
|   regs.rg_a = fd;
 | |
|   regs.rg_b = SS_FD;
 | |
|   regs.rg_x = &fdbuf;
 | |
|   regs.rg_y = sizeof (fdbuf);
 | |
| 
 | |
|   if (_os9(I_GETSTT, ®s) == -1) {
 | |
| 	errno = regs.rg_b & 0xff;
 | |
| 	return -1;
 | |
|   }
 | |
|   if (tbp)
 | |
|   {
 | |
| 	_strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
 | |
| 	tbp->t_second = 0;	/* Files are only acurate to mins */
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *	Kludge routine to return an aproximation of how many
 | |
|  *	seconds since 1980.  Dates will be in order, but will not
 | |
|  *	be lineer
 | |
|  */
 | |
| time_t cnvtime(tbp)
 | |
| struct sgtbuf *tbp;
 | |
| {
 | |
|   long acc;
 | |
| 
 | |
|   acc = tbp->t_year - 80;		/* Baseyear is 1980 */
 | |
|   acc = acc * 12 + tbp->t_month;
 | |
|   acc = acc * 31 + tbp->t_day;
 | |
|   acc = acc * 24 + tbp->t_hour;
 | |
|   acc = acc * 60 + tbp->t_minute;
 | |
|   acc = acc * 60 + tbp->t_second;
 | |
| 
 | |
|   return acc;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *	Get the current time in the internal format
 | |
|  */
 | |
| void time(tp)
 | |
| time_t *tp;
 | |
| {
 | |
|   struct sgtbuf tbuf;
 | |
| 
 | |
| 
 | |
|   if (getime(&tbuf) < 0)
 | |
| 	return -1;
 | |
| 
 | |
|   if (tp)
 | |
| 	*tp = cnvtime(&tbuf);
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *	Get the modification time of a file.  If the first
 | |
|  *	doesn't exist, it's modtime is set to 0.
 | |
|  */
 | |
| void modtime(np)
 | |
| struct name *np;
 | |
| {
 | |
| #ifdef unix
 | |
|   struct stat info;
 | |
|   int r;
 | |
| 
 | |
|   if (is_archive_ref(np->n_name)) {
 | |
| 	r = archive_stat(np->n_name, &info);
 | |
|   } else {
 | |
| 	r = stat(np->n_name, &info);
 | |
|   }
 | |
|   if (r < 0) {
 | |
| 	if (errno != ENOENT)
 | |
| 		fatal("Can't open %s: %s", np->n_name, errno);
 | |
| 
 | |
| 	np->n_time = 0L;
 | |
| 	np->n_flag &= ~N_EXISTS;
 | |
|   } else {
 | |
| 	np->n_time = info.st_mtime;
 | |
| 	np->n_flag |= N_EXISTS;
 | |
|   }
 | |
| #endif
 | |
| #ifdef tos
 | |
|   struct DOSTIME fm;
 | |
|   int fd;
 | |
| 
 | |
|   if((fd=Fopen(np->n_name,0)) < 0) {
 | |
|         np->n_time = 0L;
 | |
| 	np->n_flag &= ~N_EXISTS;
 | |
|   }
 | |
|   else {
 | |
|         Fdatime(&fm,fd,0);
 | |
|         Fclose(fd);
 | |
|         np->n_time = mstonix((unsigned int)fm.date,(unsigned int)fm.time);
 | |
|         np->n_flag |= N_EXISTS;
 | |
|   }
 | |
| #endif
 | |
| #ifdef eon
 | |
|   struct stat  info;
 | |
|   int          fd;
 | |
| 
 | |
|   if ((fd = open(np->n_name, 0)) < 0) {
 | |
| 	if (errno != ER_NOTF)
 | |
| 		fatal("Can't open %s: %s", np->n_name, errno);
 | |
| 
 | |
| 	np->n_time = 0L;
 | |
| 	np->n_flag &= ~N_EXISTS;
 | |
|   }
 | |
|   else if (getstat(fd, &info) < 0)
 | |
| 	fatal("Can't getstat %s: %s", np->n_name, errno);
 | |
|   else {
 | |
| 	np->n_time = info.st_mod;
 | |
| 	np->n_flag |= N_EXISTS;
 | |
|   }
 | |
| 
 | |
|   close(fd);
 | |
| #endif
 | |
| #ifdef os9
 | |
|   struct sgtbuf  info;
 | |
|   int            fd;
 | |
| 
 | |
|   if ((fd = open(np->n_name, 0)) < 0) {
 | |
|   if (errno != E_PNNF)
 | |
| 		fatal("Can't open %s: %s", np->n_name, errno);
 | |
| 
 | |
| 	np->n_time = 0L;
 | |
| 	np->n_flag &= ~N_EXISTS;
 | |
|   }
 | |
|   else if (getmdate(fd, &info) < 0)
 | |
| 	fatal("Can't getstat %s: %s", np->n_name, errno);
 | |
|   else {
 | |
| 	np->n_time = cnvtime(&info);
 | |
| 	np->n_flag |= N_EXISTS;
 | |
|   }
 | |
| 
 | |
|   close(fd);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *	Update the mod time of a file to now.
 | |
|  */
 | |
| void touch(np)
 | |
| struct name *np;
 | |
| {
 | |
|   char  c;
 | |
|   int   fd;
 | |
| 
 | |
|   if (!domake || !silent) printf("touch(%s)\n", np->n_name);
 | |
| 
 | |
|   if (domake) {
 | |
| #ifdef unix
 | |
| 	struct utimbuf   a;
 | |
| 
 | |
| 	a.actime = a.modtime = time((time_t *)NULL);
 | |
| 	if (utime(np->n_name, &a) < 0)
 | |
| 		printf("%s: '%s' not touched - non-existant\n",
 | |
| 				myname, np->n_name);
 | |
| #endif
 | |
| #ifdef tos
 | |
|         struct DOSTIME fm;
 | |
|         int fd;
 | |
| 
 | |
|         if((fd=Fopen(np->n_name,0)) < 0) {
 | |
|                 printf("%s: '%s' not touched - non-existant\n",
 | |
|                                 myname, np->n_name);
 | |
|         }
 | |
|         else {
 | |
|                 fm.date = Tgetdate();
 | |
|                 fm.time = Tgettime();
 | |
|                 Fdatime(&fm,fd,1);
 | |
|                 Fclose(fd);
 | |
|         }
 | |
| #endif
 | |
| #ifdef eon
 | |
| 	if ((fd = open(np->n_name, 0)) < 0)
 | |
| 		printf("%s: '%s' not touched - non-existant\n",
 | |
| 				myname, np->n_name);
 | |
| 	else
 | |
| 	{
 | |
| 		uread(fd, &c, 1, 0);
 | |
| 		uwrite(fd, &c, 1);
 | |
| 	}
 | |
| 	close(fd);
 | |
| #endif
 | |
| #ifdef os9
 | |
| 	/*
 | |
| 	 *	Strange that something almost as totally useless
 | |
| 	 *	as this is easy to do in os9!
 | |
| 	 */
 | |
| 	if ((fd = open(np->n_name, S_IWRITE)) < 0)
 | |
| 		printf("%s: '%s' not touched - non-existant\n",
 | |
| 				myname, np->n_name);
 | |
| 	close(fd);
 | |
| #endif
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  *	Recursive routine to make a target.
 | |
|  */
 | |
| int make(np, level)
 | |
| struct name *np;
 | |
| int          level;
 | |
| {
 | |
|   register struct depend  *dp;
 | |
|   register struct line    *lp;
 | |
|   register struct depend  *qdp;
 | |
|   time_t  now, t, dtime = 0;
 | |
|   bool    dbgfirst     = TRUE;
 | |
|   char   *basename  = (char *) 0;
 | |
|   char   *inputname = (char *) 0;
 | |
| 
 | |
|   if (np->n_flag & N_DONE) {
 | |
|      if(dbginfo) dbgprint(level,np,"already done");
 | |
|      return 0;
 | |
|   }
 | |
| 
 | |
|   modtime(np);		/*  Gets modtime of this file  */
 | |
| 
 | |
|   while (time(&now) == np->n_time) {
 | |
|      /* Time of target is equal to the current time.  This bothers us, because
 | |
|       * we can't tell if it needs to be updated if we update a file it depends
 | |
|       * on within a second.  So wait until the second is over.
 | |
|       */
 | |
|      usleep(10000);
 | |
|   }
 | |
| 
 | |
|   if (rules) {
 | |
|      for (lp = np->n_line; lp; lp = lp->l_next)
 | |
|         if (lp->l_cmd)
 | |
|            break;
 | |
|      if (!lp)
 | |
|         dyndep(np,&basename,&inputname);
 | |
|   }
 | |
| 
 | |
|   if (!(np->n_flag & (N_TARG | N_EXISTS))) {
 | |
|      fprintf(stderr,"%s: Don't know how to make %s\n", myname, np->n_name);
 | |
|      if (conterr) {
 | |
|         np->n_flag |= N_ERROR;
 | |
|         if (dbginfo) dbgprint(level,np,"don't know how to make");
 | |
|         return 0;
 | |
|      }
 | |
|      else  exit(1);
 | |
|   }
 | |
| 
 | |
|   for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next) {
 | |
|      for (dp = lp->l_dep; dp; dp = dp->d_next) {
 | |
|         if(dbginfo && dbgfirst) {
 | |
|            dbgprint(level,np," {");
 | |
|            dbgfirst = FALSE;
 | |
|         }
 | |
|         make(dp->d_name, level+1);
 | |
|         if (np->n_time < dp->d_name->n_time)
 | |
|            qdp = newdep(dp->d_name, qdp);
 | |
|         dtime = max(dtime, dp->d_name->n_time);
 | |
|         if (dp->d_name->n_flag & N_ERROR) np->n_flag |= N_ERROR;
 | |
|         if (dp->d_name->n_flag & N_EXEC ) np->n_flag |= N_EXEC;
 | |
|      }
 | |
|      if (!quest && (np->n_flag & N_DOUBLE) &&
 | |
|            (np->n_time < dtime || !( np->n_flag & N_EXISTS))) {
 | |
|         execflag = FALSE;
 | |
|         make1(np, lp, qdp, basename, inputname); /* free()'s qdp */
 | |
|         dtime = 0;
 | |
|         qdp = (struct depend *)0;
 | |
|         if(execflag) np->n_flag |= N_EXEC;
 | |
|      }
 | |
|   }
 | |
| 
 | |
|   np->n_flag |= N_DONE;
 | |
| 
 | |
|   if (quest) {
 | |
|      t = np->n_time;
 | |
|      np->n_time = now;
 | |
|      return (t < dtime);
 | |
|   }
 | |
|   else if ((np->n_time < dtime || !( np->n_flag & N_EXISTS))
 | |
|                && !(np->n_flag & N_DOUBLE)) {
 | |
|      execflag = FALSE;
 | |
|      make1(np, (struct line *)0, qdp, basename, inputname); /* free()'s qdp */
 | |
|      np->n_time = now;
 | |
|      if ( execflag) np->n_flag |= N_EXEC;
 | |
|   }
 | |
|   else if ( np->n_flag & N_EXEC ) {
 | |
|      np->n_time = now;
 | |
|   }
 | |
| 
 | |
|   if (dbginfo) {
 | |
|      if(dbgfirst) {
 | |
|         if(np->n_flag & N_ERROR)
 | |
|               dbgprint(level,np,"skipped because of error");
 | |
|         else if(np->n_flag & N_EXEC)
 | |
|               dbgprint(level,np,"successfully made");
 | |
|         else  dbgprint(level,np,"is up to date");
 | |
|      }
 | |
|      else {
 | |
|         if(np->n_flag & N_ERROR)
 | |
|               dbgprint(level,(struct name *)0,"} skipped because of error");
 | |
|         else if(np->n_flag & N_EXEC)
 | |
|               dbgprint(level,(struct name *)0,"} successfully made");
 | |
|         else  dbgprint(level,(struct name *)0,"} is up to date");
 | |
|      }
 | |
|   }
 | |
|   if (level == 0 && !(np->n_flag & N_EXEC))
 | |
|      printf("%s: '%s' is up to date\n", myname, np->n_name);
 | |
| 
 | |
|   if(basename)
 | |
|      free(basename);
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| void make1(np, lp, qdp, basename, inputname)
 | |
| struct name *np;
 | |
| struct line *lp;
 | |
| register struct depend *qdp;
 | |
| char        *basename;
 | |
| char        *inputname;
 | |
| {
 | |
|   register struct depend *dp;
 | |
|   size_t l1, l2;
 | |
| 
 | |
|   if (dotouch)
 | |
|     touch(np);
 | |
|   else if (!(np->n_flag & N_ERROR)) {
 | |
|     strcpy(str1, "");
 | |
| 
 | |
|     if(!inputname) {
 | |
|        inputname = str1;  /* default */
 | |
|        if (ambigmac) implmacros(np,lp,&basename,&inputname);
 | |
|     }
 | |
|     setDFmacro("<",inputname);
 | |
| 
 | |
|     if(!basename)
 | |
|        basename = str1;
 | |
|     setDFmacro("*",basename);
 | |
| 
 | |
|     for (dp = qdp; dp; dp = qdp) {
 | |
|        l1= strlen(str1);
 | |
|        l2= strlen(dp->d_name->n_name);
 | |
|        while (l1 + 1 + l2 +1 > str1s.len)
 | |
|        		strrealloc(&str1s);
 | |
|        if (strlen(str1))
 | |
|           strcat(str1, " ");
 | |
|        strcat(str1, dp->d_name->n_name);
 | |
|        qdp = dp->d_next;
 | |
|        free(dp);
 | |
|     }
 | |
|     setmacro("?", str1);
 | |
|     setDFmacro("@", np->n_name);
 | |
| 
 | |
|     if (lp)		/* lp set if doing a :: rule */
 | |
|        docmds1(np, lp);
 | |
|     else
 | |
|        docmds(np);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void implmacros(np,lp, pbasename,pinputname)
 | |
| struct name *np;
 | |
| struct line *lp;
 | |
| char        **pbasename;		/*  Name without suffix  */
 | |
| char        **pinputname;
 | |
| {
 | |
|   struct line   *llp;
 | |
|   register char *p;
 | |
|   register char *q;
 | |
|   register char *suff;				/*  Old suffix  */
 | |
|   int            baselen;
 | |
|   struct depend *dp;
 | |
|   bool           dpflag = FALSE;
 | |
| 
 | |
|   /* get basename out of target name */
 | |
|   p = str2;
 | |
|   q = np->n_name;
 | |
|   suff = suffix(q);
 | |
|   while ( *q && (q < suff || !suff)) *p++ = *q++;
 | |
|   *p = '\0';
 | |
|   if ((*pbasename = (char *) malloc(strlen(str2)+1)) == (char *)0 )
 | |
|      fatal("No memory for basename",(char *)0,0);
 | |
|   strcpy(*pbasename,str2);
 | |
|   baselen = strlen(str2);
 | |
| 
 | |
|   if ( lp)
 | |
|      llp = lp;
 | |
|   else
 | |
|      llp = np->n_line;
 | |
| 
 | |
|   while (llp) {
 | |
|      for (dp = llp->l_dep; dp; dp = dp->d_next) {
 | |
|         if( strncmp(*pbasename,dp->d_name->n_name,baselen) == 0) {
 | |
|            *pinputname = dp->d_name->n_name;
 | |
|            return;
 | |
|         }
 | |
|         if( !dpflag) {
 | |
|            *pinputname = dp->d_name->n_name;
 | |
|            dpflag = TRUE;
 | |
|         }
 | |
|      }
 | |
|      if (lp) break;
 | |
|      llp = llp->l_next;
 | |
|   }
 | |
| 
 | |
| #if NO_WE_DO_WANT_THIS_BASENAME
 | |
|   free(*pbasename);  /* basename ambiguous or no dependency file */
 | |
|   *pbasename = (char *)0;
 | |
| #endif
 | |
|   return;
 | |
| }
 | |
| 
 | |
| void dbgprint(level,np,comment)
 | |
| int          level;
 | |
| struct name *np;
 | |
| char        *comment;
 | |
| {
 | |
|   char *timep;
 | |
| 
 | |
|   if(np) {
 | |
|      timep = ctime(&np->n_time);
 | |
|      timep[24] = '\0';
 | |
|      fputs(&timep[4],stdout);
 | |
|   }
 | |
|   else fputs("                    ",stdout);
 | |
|   fputs("   ",stdout);
 | |
|   while(level--) fputs("  ",stdout);
 | |
|   if (np) {
 | |
|      fputs(np->n_name,stdout);
 | |
|      if (np->n_flag & N_DOUBLE) fputs("  :: ",stdout);
 | |
|      else                       fputs("  : ",stdout);
 | |
|   }
 | |
|   fputs(comment,stdout);
 | |
|   putchar((int)'\n');
 | |
|   fflush(stdout);
 | |
|   return;
 | |
| }
 | |
| 
 | 
