#include "make.h"

#define GETNEWTIME (-1)
#define ERRORTIME (-2)

long make(what)
char *what;
   {
   TNODE       *snode, *vnode;             /* Source file node pointer */
   STRNODE     *nodep, *newlist, *newnode, *makestr();
   long        modified;
   long        targettime;
   char        buffer[MAXBUFF], *command, *p;
   char        *stpblk(), *copystr();
   int         rc;
   char        QuietOne, CanHaveError, doaction, badbranch;

   tstbreak();

#ifdef DEBUG
   if (DebugMode)
      msg("Makeone enter for %s\n", what);
#endif
   if ( !(snode = (TNODE *)find(what, Root)) )
      {
      /* create a dummy node to fool them */
      snode = (TNODE *) gmem( sizeof(TNODE) );
      snode->targets    = makestr( what );
      snode->depends    = NULL;  /* no dependancies */
      snode->commands   = NULL;  /* and no action */
      tree(what, snode, &Root);

      /* check to see if any defaults exist for this type of file */
      SimpleMacro( what, &buffer, MAXBUFF );

      /* now look at it and see if it ends in a .o */
      p = buffer + (strlen(buffer) - 1);
      if (*(p-1) == '.' && *p == 'o')
         {
         /* see if we can find a .c file of the same ilk */
         *p = 'c';
#ifdef DEBUG
         if (DebugMode)
            {
            msg("Checking for %s\n", buffer);
            msg(" to satisfy %s\n", what);
            }
#endif
         /* first see if we can open the file */
         if (exist(buffer))
            {
#ifdef DEBUG
            if (DebugMode)
               msg("Got it as a C file\n");
#endif
            snode->depends = (STRNODE *)makestr( copystr(buffer) );
            if ((vnode = (TNODE *)find(".c.o", Root)) != NULL)
               snode->commands = vnode->commands;
#ifdef DEBUG
            if (DebugMode)
               msg("Depends upon %s\n", snode->depends->string);
#endif
            }
         else
            {
            *p = 'a';
#ifdef DEBUG
            if (DebugMode)
               {
               msg("Checking for %s", buffer);
               msg(" to satisfy %s\n", what);
               }
#endif
            if (exist(buffer))
               {
               snode->depends = (STRNODE *)makestr( copystr(buffer) );
               if ((vnode = (TNODE *)find(".a.o", Root)) != NULL)
                  snode->commands = vnode->commands;
               }
            }
         }
      }

   newlist = NULL;
   badbranch = FALSE;
   doaction = AlwaysRebuild || (snode->depends == NULL);

   /* figure out the oldest time of any of the referenced files */
   targettime = timenow();

   for (nodep = snode->targets; nodep != NULL; nodep=nodep->next)
      {
      long filetime;
      tstbreak();

      /* expand any macros in the name */
      SimpleMacro( nodep->string, &buffer, MAXBUFF );
      filetime = gtime(buffer);
      if (filetime < targettime) targettime = filetime;
      }

   for (nodep = snode->depends; nodep != NULL; nodep=nodep->next)
      {
      /* expand list of files */
      if ( (modified = make( nodep->string )) == ERRORTIME)
         badbranch = TRUE;

#ifdef DEBUG
      if (DebugMode)
         {
         msg("source file:" );
         ptime( what, targettime );
         msg("dependent file:" );
         ptime( nodep->string, modified );
         }
#endif
      if ( targettime <= modified )
         {
         /* add the current item to the action list */
         newnode = makestr( nodep->string );
         newnode->next = newlist;
         newlist = newnode;

         if (QuestionMode)
            exit(10);

         doaction = 1;
         }
      }

   if (doaction && !badbranch)
      {
      APTR spawned = NULL;
      APTR SpawnCLI();
      tstbreak();

      for ( nodep = snode->commands; nodep != NULL; nodep=nodep->next)
         {
	 if (NoExecuteMode)
	    tstbreak();
         /* skip over any silence/error ignore flags */
         command = stpblk(nodep->string);

         if ( (QuietOne = (*command == '@')) )
            command++;

         if ( (CanHaveError = (*command == '-')) )
            {
            command++;
            /* one last check to allow -@ */
            if (!QuietOne && (*command == '@'))
               {
               command++;
               QuietOne = TRUE;
               }
            }

         ExpandMacros(command, cmdbuff, MAXBUFF, snode, newlist);

         if ( (!SilentMode && !QuietOne) || NoExecuteMode)
            {
            Write(OutputFile, cmdbuff, strlen(cmdbuff) );
            Write(OutputFile, "\n", 1);
            }

         if (!NoExecuteMode)
            {

            /* handle the DontPrintErrors Flag here */
            if (!spawned && !(spawned = SpawnCLI()))
               err("Can't spawn CLI process\n", 0);
	       
            rc = ExecCLI(spawned, cmdbuff);
	    if (BreakCLI(spawned) == 'C')
	    {
	       KillCLI(spawned);
	       err("***BREAK\n");
	    }

            targettime = GETNEWTIME;
            if (rc)
               {
               if (!CanHaveError && !IgnoreErrors)
                  {
                  if (ContinueBranches)
                     targettime = ERRORTIME;
                  else
                     {
		     KillCLI(spawned);
                     err("Can't process <%s>\n", buffer );
                     }
                  }
               }
            }
         else
            targettime = timenow();
         }
      if (spawned)
	 {
         int brk = BreakCLI(spawned);
         KillCLI(spawned);
         if (brk) err("***BREAK\n");
	 }
      }

   if (targettime == GETNEWTIME)
      {
      SimpleMacro( what, &buffer, MAXBUFF );
      targettime = gtime(buffer);
      }

#ifdef DEBUG
   if (DebugMode)
      msg("Makeone exit for %s\n", what);
#endif
   return ( (badbranch) ? ERRORTIME : targettime );
   }
