bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v4 2/3] Support per-target .ONESHELL


From: Britton Leo Kerin
Subject: [RFC PATCH v4 2/3] Support per-target .ONESHELL
Date: Mon, 23 Dec 2024 15:56:47 -0900

---
 src/commands.c | 206 ++++++++++++++++++++++++++++++++++---------------
 src/commands.h |  18 ++++-
 src/default.c  |   3 +
 src/file.c     |  11 +++
 src/filedef.h  |   2 +
 src/job.c      | 111 +++++++++++++++++++++-----
 src/main.c     |   9 ++-
 src/makeint.h  |   2 +-
 src/read.c     |   8 --
 src/remake.c   |  34 ++++++--
 10 files changed, 301 insertions(+), 103 deletions(-)

diff --git a/src/commands.c b/src/commands.c
index 343c1cb5..ea5a8164 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -317,22 +317,46 @@ set_file_variables (struct file *file, const char *stem)
 }
 
 /* Chop CMDS up into individual command lines if necessary.
-   Also set the 'lines_flags' and 'any_recurse' members.  */
-
+   Also set the 'lines_flags' and 'any_recurse' members.  ONESHELL_TARGET
+   indicates that the commands are being prepared for a target that is a
+   prerequisite of .ONESHELL: */
+
+// FIXME: above phrase is garbage.  The extra fields in struct commands
+// (e.g. oneshell_command_lines) are weird and confusing.  They should
+// probably at least be packed into their own structure called maybe
+// commands_per_target_oneshell or something.  The roots of all this mess
+// are the strategy of mutating struct commands, and the lack of any OO
+// to support mutation.  The mutability could in theory be changed by
+// demand-computing command_lines or something, but that cold be pretty
+// inefficient.  I guess it could be memoized or something but that sounds
+// sort of weird.  Actually I think we want struct commands_traditional
+// and struct commands_oneshell, and struct commands has pointers to both,
+// and either or both can be non-NULL.  But that would involve significant
+// changes even when no per-target ONESHELL was happening.  Also notable
+// that struct commands_traditional and struct commands_oneshell would have
+// all the same fields, really those should be different pointers to the
+// same structure type.  Hmmm
+//
+// FIXME: doc the oneshell_target arg, and consider it's name further
+// UPDATE: should it be support oneshell_targets or just support_oneshell?
+// I think I like support_oneshell_targets, but that's still misleading
+// becaues what we really mean given how things work at the moment is
+// support_per_target_oneshell_targets
 void
-chop_commands (struct commands *cmds)
+chop_commands (struct commands *cmds, int support_oneshell_target)
 {
   unsigned short nlines;
   unsigned short i;
   char **lines;
 
-  /* If we don't have any commands, or we already parsed them, never mind.  */
-  if (!cmds || cmds->command_lines != NULL)
+  /* If we don't have any commands, or we already parsed them for non-oneshell
+   * and possible one-shell use as requested, never mind.  */
+  if (!cmds || ((cmds->command_lines != NULL) && ((!support_oneshell_target) 
|| (cmds->oneshell_command_lines != NULL))))
     return;
 
   /* Chop CMDS->commands up into lines in CMDS->command_lines.  */
 
-  if (one_shell)
+  if (all_one_shell)
     {
       size_t l = strlen (cmds->commands);
 
@@ -346,49 +370,103 @@ chop_commands (struct commands *cmds)
     }
   else
     {
-      const char *p = cmds->commands;
-      size_t max = 5;
-
-      nlines = 0;
-      lines = xmalloc (max * sizeof (char *));
-      while (*p != '\0')
+      if ( support_oneshell_target )
         {
-          const char *end = p;
-        find_end:;
-          end = strchr (end, '\n');
-          if (end == NULL)
-            end = p + strlen (p);
-          else if (end > p && end[-1] == '\\')
+          // FIXME: this paragraph and next are common functionality with the
+          // code in all_one_shell and if everything works should perhaps be
+          // modularized somehow.  Or this entire function rewritten
+          size_t l = strlen (cmds->commands);
+          unsigned short oneshell_nlines = 1;
+          // FIXME: needs corresponding free if make frees things
+          char **oneshell_lines = xmalloc (oneshell_nlines * sizeof (char *));
+          oneshell_lines[0] = xstrdup (cmds->commands);
+
+          /* Strip the trailing newline.  */
+          if (l > 0 && oneshell_lines[0][l-1] == '\n')
+            oneshell_lines[0][l-1] = '\0';
+
+          cmds->oneshell_ncommand_lines = oneshell_nlines;
+          cmds->oneshell_command_lines = oneshell_lines;
+
+          cmds->oneshell_any_recurse = 0;
+          // FIXME: needs corresponding free if make frees things
+          cmds->oneshell_lines_flags = xmalloc (oneshell_nlines);
+
+          for (i = 0; i < oneshell_nlines; ++i)
             {
-              int backslash = 1;
-              if (end > p + 1)
-                {
-                  const char *b;
-                  for (b = end - 2; b >= p && *b == '\\'; --b)
-                    backslash = !backslash;
-                }
-              if (backslash)
+              unsigned char flags = 0;
+              const char *p = oneshell_lines[i];
+
+              while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
+                switch (*(p++))
                 {
-                  ++end;
-                  goto find_end;
+                  case '+':
+                    flags |= COMMANDS_RECURSE;
+                    break;
+                  case '@':
+                    flags |= COMMANDS_SILENT;
+                    break;
+                  case '-':
+                    flags |= COMMANDS_NOERROR;
+                    break;
                 }
-            }
 
-          if (nlines == USHRT_MAX)
-            ON (fatal, &cmds->fileinfo,
-                _("recipe has too many lines (limit %hu)"), nlines);
+              /* If no explicit '+' was given, look for MAKE variable
+               * references. */
+              if (! ANY_SET (flags, COMMANDS_RECURSE)
+                  && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 
0))
+                flags |= COMMANDS_RECURSE;
 
-          if (nlines == max)
-            {
-              max += 2;
-              lines = xrealloc (lines, max * sizeof (char *));
+              cmds->oneshell_lines_flags[i] = flags;
+              cmds->oneshell_any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) 
? 1 : 0;
             }
+      }
 
-          lines[nlines++] = xstrndup (p, (size_t) (end - p));
-          p = end;
-          if (*p != '\0')
-            ++p;
-        }
+      {
+        const char *p = cmds->commands;
+        size_t max = 5;
+
+        nlines = 0;
+        lines = xmalloc (max * sizeof (char *));
+        while (*p != '\0')
+          {
+            const char *end = p;
+          find_end:;
+            end = strchr (end, '\n');
+            if (end == NULL)
+              end = p + strlen (p);
+            else if (end > p && end[-1] == '\\')
+              {
+                int backslash = 1;
+                if (end > p + 1)
+                  {
+                    const char *b;
+                    for (b = end - 2; b >= p && *b == '\\'; --b)
+                      backslash = !backslash;
+                  }
+                if (backslash)
+                  {
+                    ++end;
+                    goto find_end;
+                  }
+              }
+
+            if (nlines == USHRT_MAX)
+              ON (fatal, &cmds->fileinfo,
+                  _("recipe has too many lines (limit %hu)"), nlines);
+
+            if (nlines == max)
+              {
+                max += 2;
+                lines = xrealloc (lines, max * sizeof (char *));
+              }
+
+            lines[nlines++] = xstrndup (p, (size_t) (end - p));
+            p = end;
+            if (*p != '\0')
+              ++p;
+          }
+      }
     }
 
   /* Finally, set the corresponding CMDS->lines_flags elements and the
@@ -401,32 +479,32 @@ chop_commands (struct commands *cmds)
   cmds->lines_flags = xmalloc (nlines);
 
   for (i = 0; i < nlines; ++i)
-    {
-      unsigned char flags = 0;
-      const char *p = lines[i];
+  {
+    unsigned char flags = 0;
+    const char *p = lines[i];
 
-      while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
-        switch (*(p++))
-          {
-          case '+':
-            flags |= COMMANDS_RECURSE;
-            break;
-          case '@':
-            flags |= COMMANDS_SILENT;
-            break;
-          case '-':
-            flags |= COMMANDS_NOERROR;
-            break;
-          }
+    while (ISBLANK (*p) || *p == '-' || *p == '@' || *p == '+')
+      switch (*(p++))
+      {
+        case '+':
+          flags |= COMMANDS_RECURSE;
+          break;
+        case '@':
+          flags |= COMMANDS_SILENT;
+          break;
+        case '-':
+          flags |= COMMANDS_NOERROR;
+          break;
+      }
 
-      /* If no explicit '+' was given, look for MAKE variable references.  */
-      if (! ANY_SET (flags, COMMANDS_RECURSE)
-          && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
-        flags |= COMMANDS_RECURSE;
+    /* If no explicit '+' was given, look for MAKE variable references.  */
+    if (! ANY_SET (flags, COMMANDS_RECURSE)
+        && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0))
+      flags |= COMMANDS_RECURSE;
 
-      cmds->lines_flags[i] = flags;
-      cmds->any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) ? 1 : 0;
-    }
+    cmds->lines_flags[i] = flags;
+    cmds->any_recurse |= ANY_SET (flags, COMMANDS_RECURSE) ? 1 : 0;
+  }
 }
 
 /* Execute the commands to remake FILE.  If they are currently executing,
diff --git a/src/commands.h b/src/commands.h
index 9451b68b..b26c38ec 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -27,6 +27,22 @@ struct commands
     char recipe_prefix;         /* Recipe prefix for this command set.  */
     unsigned int any_recurse:1; /* Nonzero if any 'lines_flags' elt has */
                                 /* the COMMANDS_RECURSE bit set.  */
+    /* These are like the correspondingly namned variables above, but are
+     * needed only when commands that are recipes for targets that are
+     * prerequisites of the .ONESHELL: special target are to be run.  They
+     * aren't used when all_one_shell is used, because in that case we just
+     * keep the one shell version in the above variables.  They're needed
+     * when per-target .ONESHELL is used because the commands structures for
+     * implicit rules, .DEFAULT: rules, and suffix rules are shared and
+     * both oneshell and non-oneshell targets might be using this structure.
+     */
+    char **oneshell_command_lines;/* ONLY for .ONESHELL: with prereqs  */
+    unsigned char *oneshell_lines_flags;/* ONLY for .ONESHELL: with prereqs */
+    // FIXME: this next one is especially silly in the oneline-specific world.
+    // probaly all we ultimately need in oneshell world is
+    // oneshell_command_no_newline or so
+    unsigned short oneshell_ncommand_lines;/* ONLY for .ONESHELL: with prereqs 
*/
+    unsigned int oneshell_any_recurse:1;  /* ONLY for .ONESHELL: with prereqs 
*/
   };
 
 /* Bits in 'lines_flags'.  */
@@ -41,5 +57,5 @@ void fatal_error_signal (int sig);
 void execute_file_commands (struct file *file);
 void print_commands (const struct commands *cmds);
 void delete_child_targets (struct child *child);
-void chop_commands (struct commands *cmds);
+void chop_commands (struct commands *cmds, int support_oneshell_target);
 void set_file_variables (struct file *file, const char *stem);
diff --git a/src/default.c b/src/default.c
index c731817e..85a8e137 100644
--- a/src/default.c
+++ b/src/default.c
@@ -715,6 +715,9 @@ install_default_suffix_rules ()
   for (s = default_suffix_rules; *s != 0; s += 2)
     {
       struct file *f = enter_file (strcache_add (s[0]));
+      // FIXME: The comment above this function says we're doing this before
+      // reading  makefiles, so how can there be a user-defined rule here?  I
+      // think it  must mean before *re*-reading makefiles.
       /* Install the default rule only if there is no user defined rule.  */
       if (!f->cmds)
         {
diff --git a/src/file.c b/src/file.c
index 6f816c8a..2b9a46ef 100644
--- a/src/file.c
+++ b/src/file.c
@@ -830,6 +830,17 @@ snap_deps (void)
     else
       no_intermediates = 1;
 
+#if !MK_OS_DOS && !MK_OS_OS2
+  for (f = lookup_file (".ONESHELL"); f != 0; f = f->prev)
+    if (f->deps)
+      for (d = f->deps; d != 0; d = d->next)
+        for (f2 = d->file; f2 != 0; f2 = f2->prev)
+          f2->oneshell = 1;
+    /* .ONESHELL with no deps marks all files as one_shell.  (*/
+    else
+      all_one_shell = 1;
+#endif
+
   /* The same file cannot be both .INTERMEDIATE and .NOTINTERMEDIATE.
      However, it is possible for a file to be .INTERMEDIATE and also match a
      .NOTINTERMEDIATE pattern.  In that case, the intermediate file has
diff --git a/src/filedef.h b/src/filedef.h
index b2ef1a16..8dd3fe08 100644
--- a/src/filedef.h
+++ b/src/filedef.h
@@ -102,6 +102,8 @@ struct file
                                    not delete it.  */
     unsigned int notintermediate:1; /* Nonzero means a file is a prereq to
                                        .NOTINTERMEDIATE.  */
+    unsigned int oneshell:1;    /* Nonzero means entire recipe should be run in
+                                   a single shell.  */
     unsigned int dontcare:1;    /* Nonzero if no complaint is to be made if
                                    this target cannot be remade.  */
     unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name.  */
diff --git a/src/job.c b/src/job.c
index e54a9340..f0a7f6cb 100644
--- a/src/job.c
+++ b/src/job.c
@@ -19,6 +19,8 @@ this program.  If not, see <https://www.gnu.org/licenses/>.  
*/
 #include <assert.h>
 #include <string.h>
 
+#include "myMakeLog.h"
+
 /* Default shell to use.  */
 #if MK_OS_W32
 # include <windows.h>
@@ -1130,7 +1132,37 @@ free_child (struct child *child)
   if (child->command_lines != 0)
     {
       unsigned int i;
-      for (i = 0; i < child->file->cmds->ncommand_lines; ++i)
+      unsigned short ncommand_lines;
+      if ( child->file->oneshell ) {
+        ncommand_lines = child->file->cmds->oneshell_ncommand_lines;
+        // FIXME: WORK POINT: well this checkpoint hits with a built-in
+        // implicit rule but how do we test this from a test, since the
+        // built-in rules are all one line?  Just add a comment to the test
+        // script indicating that it's been tried, and that things have been
+        // arranged that way to avoid changing code paths for the built-in
+        // suffix and implicit rules?  Same issue when built-in suffix rules
+        // are triggered (though for all I know they essentially compile
+        // to the corresponding implicit rule with which they shave a cmds
+        // structure (I sort of think they don't but I'd need to check)
+        //
+        // Other things that I've tried that still need tests written:
+        //   * match-anything implicit terminal rules (::)
+        //   * match-anything implicit non-terminal rules (not ::)
+        //   * implicit rules
+        //   * .DEFAULT rules
+        //   * double-suffix rules
+        //   * single-suffic rules
+        //
+        // Things that haven't been tried yet:
+        //   * That all the line flags (no output, no errors, recurse, and
+        //     recurse due to $(MAKE)) var ref work as documented
+        //
+        mCP ();
+      }
+      else {
+        ncommand_lines = child->file->cmds->ncommand_lines;
+      }
+      for (i = 0; i < ncommand_lines; ++i)
         free (child->command_lines[i]);
       free (child->command_lines);
     }
@@ -1167,8 +1199,14 @@ start_job_command (struct child *child)
 
   /* Combine the flags parsed for the line itself with
      the flags specified globally for this target.  */
-  flags = (child->file->command_flags
-           | child->file->cmds->lines_flags[child->command_line - 1]);
+  if ( child->file->oneshell ) {
+    flags = (child->file->command_flags
+             | child->file->cmds->oneshell_lines_flags[child->command_line - 
1]);
+  }
+  else {
+    flags = (child->file->command_flags
+             | child->file->cmds->lines_flags[child->command_line - 1]);
+  }
 
   p = child->command_ptr;
   child->noerror = ANY_SET (flags, COMMANDS_NOERROR);
@@ -1195,7 +1233,12 @@ start_job_command (struct child *child)
      multiline define/endef scripts where only one line is marked "+".  In
      order to really fix this, we'll have to keep a lines_flags for every
      actual line, after expansion.  */
-  child->file->cmds->lines_flags[child->command_line - 1] |= flags & 
COMMANDS_RECURSE;
+  if ( child->file->oneshell ) {
+    child->file->cmds->oneshell_lines_flags[child->command_line - 1] |= flags 
& COMMANDS_RECURSE;
+  }
+  else {
+    child->file->cmds->lines_flags[child->command_line - 1] |= flags & 
COMMANDS_RECURSE;
+  }
 
   /* POSIX requires that a recipe prefix after a backslash-newline should
      be ignored.  Remove it now so the output is correct.  */
@@ -1655,6 +1698,9 @@ new_job (struct file *file)
   struct child *c;
   char **lines;
   unsigned int i;
+  char **command_lines;
+  unsigned short ncommand_lines;
+
 
   /* Let any previously decided-upon jobs that are waiting
      for the load to go down start before this new one.  */
@@ -1664,7 +1710,7 @@ new_job (struct file *file)
   reap_children (0, 0);
 
   /* Chop the commands up into lines if they aren't already.  */
-  chop_commands (cmds);
+  chop_commands (cmds, file->oneshell);
 
   /* Start the command sequence, record it in a new
      'struct child', and add that to the chain.  */
@@ -1682,9 +1728,18 @@ new_job (struct file *file)
   /* Start saving output in case the expansion uses $(info ...) etc.  */
   OUTPUT_SET (&c->output);
 
+  if ( file->oneshell ) {
+    command_lines = cmds->oneshell_command_lines;
+    ncommand_lines = cmds->oneshell_ncommand_lines;
+  }
+  else {
+    command_lines = cmds->command_lines;
+    ncommand_lines = cmds->ncommand_lines;
+  }
+
   /* Expand the command lines and store the results in LINES.  */
-  lines = xmalloc (cmds->ncommand_lines * sizeof (char *));
-  for (i = 0; i < cmds->ncommand_lines; ++i)
+  lines = xmalloc (ncommand_lines * sizeof (char *));
+  for (i = 0; i < ncommand_lines; ++i)
     {
       /* Collapse backslash-newline combinations that are inside variable
          or function references.  These are left alone by the parser so
@@ -1700,7 +1755,7 @@ new_job (struct file *file)
          When we collapse a backslash-newline combination,
          IN gets ahead of OUT.  */
 
-      in = out = cmds->command_lines[i];
+      in = out = command_lines[i];
       while ((ref = strchr (in, '$')) != 0)
         {
           ++ref;                /* Move past the $.  */
@@ -1781,8 +1836,7 @@ new_job (struct file *file)
 
       /* Finally, expand the line.  */
       cmds->fileinfo.offset = i;
-      lines[i] = allocated_expand_string_for_file (cmds->command_lines[i],
-                                                   file);
+      lines[i] = allocated_expand_string_for_file (command_lines[i], file);
     }
 
   cmds->fileinfo.offset = 0;
@@ -1961,8 +2015,15 @@ job_next_command (struct child *child)
 {
   while (child->command_ptr == 0 || *child->command_ptr == '\0')
     {
+      unsigned short ncommand_lines;
+      if ( child->file->oneshell ) {
+        ncommand_lines = child->file->cmds->oneshell_ncommand_lines;
+      }
+      else {
+        ncommand_lines = child->file->cmds->ncommand_lines;
+      }
       /* There are no more lines in the expansion of this line.  */
-      if (child->command_line == child->file->cmds->ncommand_lines)
+      if (child->command_line == ncommand_lines)
         {
           /* There are no more lines to be expanded.  */
           child->command_ptr = 0;
@@ -2699,9 +2760,10 @@ exec_command (char **argv, char **envp)
    (see the FREE_ARGV macro).  */
 
 static char **
-construct_command_argv_internal (char *line, char **restp, const char *shell,
-                                 const char *shellflags, const char *ifs,
-                                 int flags, char **batch_filename UNUSED)
+construct_command_argv_internal (char *line, char **restp, int one_shell,
+                                 const char *shell, const char *shellflags,
+                                 const char *ifs, int flags,
+                                 char **batch_filename UNUSED)
 {
 #if MK_OS_DOS
   /* MSDOS supports both the stock DOS shell and ports of Unixy shells.
@@ -3369,12 +3431,16 @@ construct_command_argv_internal (char *line, char 
**restp, const char *shell,
             }
           else
             {
+              // FIXME: is it appropriate to pass one_shell here?  We got all
+              // these other zeros being passed and it seems like it's being
+              // used for a weird different internal purpose
               /* Parse shellflags using construct_command_argv_internal to
                  handle quotes. */
               char **argv;
               char *f = alloca (sflags_len + 1);
               memcpy (f, shellflags, sflags_len + 1);
-              argv = construct_command_argv_internal (f, 0, 0, 0, 0, flags, 0);
+              argv = construct_command_argv_internal (f, 0, one_shell, 0, 0, 
0, flags, 0);
+
               if (argv)
                 {
                   char **a;
@@ -3528,9 +3594,12 @@ construct_command_argv_internal (char *line, char 
**restp, const char *shell,
     else
 #endif /* MK_OS_W32 */
 
+    // FIXME: is it appropriate to pass one_shell here?  We got all these
+    // other zeros being passed and it seems like it's being used for a
+    // weird different internal purpose
     if (unixy_shell)
-      new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0,
-                                                  flags, 0);
+      new_argv = construct_command_argv_internal (new_line, 0, one_shell, 0, 0,
+                                                  0, flags, 0);
 
 #if MK_OS_OS2
     else if (!unixy_shell)
@@ -3727,8 +3796,12 @@ construct_command_argv (char *line, char **restp, struct 
file *file,
     warn_set (wt_undefined_var, save);
   }
 
-  argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs,
-                                          cmd_flags, batch_filename);
+  // FIXME: since we're renaming the one_shell global anyway wouldn't
+  // all_oneshell be a nicer name?
+  argv = construct_command_argv_internal (line, restp,
+                                          all_one_shell || file->oneshell,
+                                          shell, shellflags, ifs, cmd_flags,
+                                          batch_filename);
 
   free (shell);
   free (allocflags);
diff --git a/src/main.c b/src/main.c
index a92b2ace..ccfd9795 100644
--- a/src/main.c
+++ b/src/main.c
@@ -589,11 +589,12 @@ int posix_pedantic;
 
 int second_expansion;
 
-/* Nonzero if we have seen the '.ONESHELL' target.
-   This causes the entire recipe to be handed to SHELL
-   as a single string, potentially containing newlines.  */
+/* Nonzero if we have seen the '.ONESHELL' target without
+   prerequisites. FIXME: clunky language: For all targets, this causes the 
entire
+   recipe to be handed to SHELL as a single string, potentially
+   containing newlines.  */
 
-int one_shell;
+int all_one_shell;
 
 /* One of OUTPUT_SYNC_* if the "--output-sync" option was given.  This
    attempts to synchronize the output of parallel jobs such that the results
diff --git a/src/makeint.h b/src/makeint.h
index 61c78229..41102e43 100644
--- a/src/makeint.h
+++ b/src/makeint.h
@@ -734,7 +734,7 @@ extern int print_data_base_flag, question_flag, touch_flag, 
always_make_flag;
 extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag;
 extern int print_version_flag, check_symlink_flag, posix_pedantic;
 extern int not_parallel, second_expansion, clock_skew_detected;
-extern int rebuilding_makefiles, one_shell, output_sync, verify_flag;
+extern int rebuilding_makefiles, all_one_shell, output_sync, verify_flag;
 extern int export_all_variables;
 extern unsigned long command_count;
 
diff --git a/src/read.c b/src/read.c
index 2e30ce17..e00a4df6 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1892,14 +1892,6 @@ check_specials (struct nameseq *files, int set_default)
           continue;
         }
 
-#if !MK_OS_DOS && !MK_OS_OS2
-      if (!one_shell && streq (nm, ".ONESHELL"))
-        {
-          one_shell = 1;
-          continue;
-        }
-#endif
-
       /* Determine if this target should be made default.  */
 
       if (set_default && default_goal_var->value[0] == '\0')
diff --git a/src/remake.c b/src/remake.c
index 9d7ae8fd..74f1d37f 100644
--- a/src/remake.c
+++ b/src/remake.c
@@ -1003,6 +1003,8 @@ notice_finished_file (struct file *file)
   file->command_state = cs_finished;
   file->updated = 1;
 
+  // FIXME: need a test to see if this stuff works under -t, ug what a pain
+  // need to make recursive invocations somehow in the test script
   if (touch_flag
       /* The update status will be:
            us_success   if 0 or more commands (+ or ${MAKE}) were run and won;
@@ -1014,11 +1016,21 @@ notice_finished_file (struct file *file)
     {
       if (file->cmds != 0 && file->cmds->any_recurse)
         {
+          unsigned short ncommand_lines;
+          unsigned char *lines_flags;
+          unsigned int i;
+          if ( file->oneshell ) {
+            ncommand_lines = file->cmds->oneshell_ncommand_lines;
+            lines_flags = file->cmds->oneshell_lines_flags;
+          }
+          else {
+            ncommand_lines = file->cmds->ncommand_lines;
+            lines_flags = file->cmds->lines_flags;
+          }
           /* If all the command lines were recursive,
              we don't want to do the touching.  */
-          unsigned int i;
-          for (i = 0; i < file->cmds->ncommand_lines; ++i)
-            if (NONE_SET (file->cmds->lines_flags[i], COMMANDS_RECURSE))
+          for (i = 0; i < ncommand_lines; ++i)
+            if (NONE_SET (lines_flags[i], COMMANDS_RECURSE))
               goto have_nonrecursing;
         }
       else
@@ -1058,8 +1070,18 @@ notice_finished_file (struct file *file)
 
       if ((question_flag || just_print_flag || touch_flag) && file->cmds)
         {
-          for (i = file->cmds->ncommand_lines; i > 0; --i)
-            if (NONE_SET (file->cmds->lines_flags[i-1], COMMANDS_RECURSE))
+          unsigned short ncommand_lines;
+          unsigned char *lines_flags;
+          if ( file->oneshell ) {
+            ncommand_lines = file->cmds->oneshell_ncommand_lines;
+            lines_flags = file->cmds->oneshell_lines_flags;
+          }
+          else {
+            ncommand_lines = file->cmds->ncommand_lines;
+            lines_flags = file->cmds->lines_flags;
+          }
+          for (i = ncommand_lines; i > 0; --i)
+            if (NONE_SET (lines_flags[i-1], COMMANDS_RECURSE))
               break;
         }
 
@@ -1369,7 +1391,7 @@ remake_file (struct file *file)
     }
   else
     {
-      chop_commands (file->cmds);
+      chop_commands (file->cmds, file->oneshell);
 
       /* The normal case: start some commands.  */
       if (!touch_flag || file->cmds->any_recurse)
-- 
2.43.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]