Ok...

Lets try splitting some of the issues brought up into a separate patch (attached, log below). This patch focuses on the snprintf issue, the use of asserts(), and centralizing filename generation logic. Included is the file name token abstraction logic. The possibility was raised that path separators may be more than one character long. I would agree that it should be considered, but I also feel that to code for this possibility would slow the program down slightly, for no immediate benefit, as all current target platforms seem to use a single character as the directory separator.

--Andrew Black

Log:
* util.h (reference_name, output_name): Declare functions to generate the names for reference and output files respectively.
        * util.cpp (reference_name, output_name): Define above.
        * util.cpp (guarded_malloc, guarded_realloc): move use of size asserts
* cmdopt.h (escape_code, default_path_sep, suffix_len, suffix_sep): Declare (platform specific) file system related constants. * cmdopt.cpp (escape_code, default_path_sep, suffix_len, suffix_sep): Define above for unix systems.
        * cmdopt.cpp (split_opt_string): Move use of opts after assert
* cmdopt.cpp (split_opt_string): Use escape_code as escape character in place of '\'. * exec.cpp (get_signame): Enlarge static buffer, use sprintf in place of snprintf.
        * exec.cpp (open_input): Move use of in_root after asserts.
* exec.cpp (open_input, exec_file): Alter to use reference_name, output_name respectively to determine file locations. * output.cpp (check_example): Move use of in_root after asserts, use reference_name to determine reference file location.
        * output.cpp (parse_output): Use output_name to determine output file 
name
* runall.cpp (merge_argv, run_target): Use target, argv, childargv after asserts * runall.cpp (check_target_ok): Disable (unused) logic for output only targets. Alter compile check on windows systems to correctly locate .obj file.
        * runall.cpp (rw_basename): Use default_path_sep as separator.

Martin Sebor wrote:
Andrew Black wrote:
Greetings

Attached is a reworked version of the patch with the requested changes included. Unfortunately, the change log has changed enough that a new one is required.

That's okay, we don't mind :)

If it is decided that the windows file structure is to be altered (with regards to the location of object files), this patch will need to be altered slightly.

One that was asked was 'Why can't we use backslash as the escape character on Windows?' My answer is that the character is used as a path separator,

Ugh.

and it would be impossible to disambiguate the conflicting uses. I use ^ as the escape character on windows, as that's the escape character used elsewhere in windows.

Another question that was asked was about the block I #if 0 ed out. This change was intentional. The block in question is/was used to check compile only targets, but we don't have any of those at this time. IF this check were to be kept, it would need platform specific logic to handle the differences in suffixes for object files between windows and unix.

Okay. Thanks for adding the comment.


--Andrew Black

Log:

Wow! Capitalized first letter in every sentence and all. I'm so
proud of you! ;-)

* util.h (rw_snprintf): Add macro hack to work around lack of snprintf definition on windows. * util.h (reference_name, output_name): Declare functions to generate the names for reference and output files respectively.
    * util.cpp (reference_name, output_name): Define above.
* cmdopt.h (escape_code, default_path_sep, suffix_len): Declare platform specific constants related to the file system. * cmdopt.cpp (escape_code, default_path_sep, suffix_len): Define above, conditional on platform. * cmdopt.cpp: Alter #includes to include windows.h on windows in place of unistd.h. * cmdopt.cpp (rw_sleep, rw_signal): Define platform abstraction functions for sleep and signal/sigaction, conditional on platform. * cmdopt.cpp (eval_options): use use rw_sleep() in place of sleep(), rw_signal() in place of sigaction(). * cmdopt.cpp (split_opt_string): use escape_code as escape character in place of '\'.
    * exec.h (exec_attrs): Alter structure for windows builds.
* exec.cpp: Alter #includes to include windows.h and process.h on windows in place of unistd.h and sys/wait.h
    * exec.cpp (get_signame): Use rw_snprintf in place of snprintf.
* exec.cpp (handle_alrm, wait_for_child, open_input, replace_file, exec_file): Compile (existing) versions only on non-windows platforms. * exec.cpp (open_input, exec_file): Alter (existing) version to use reference_name, output_name respectively. * exec.cpp (open_input, merge_argv, exec_file): Define new functions using windows native API, which will compile only on windows platforms. * output.cpp (check_example): Use reference_name to determine reference file location. * runall.cpp (S_IXUSR, S_IXGRP, S_IXOTH): Define if not defined for windows. * runall.cpp (check_target_ok): Disable (unused) logic for output only targets. Alter compile check on windows systems to correctly locate .obj file. * runall.cpp (process_results): Handle windows result codes correctly. * runall.cpp (rw_basename): Use default_path_sep as separator for non-windows builds.


------------------------------------------------------------------------

Index: util.h
===================================================================
--- util.h    (revision 430088)
+++ util.h    (working copy)
@@ -28,6 +28,15 @@
 #define RW_UTIL_H
/**
+   Ugly workaround for windows non-definition of snprintf

snprintf() is a C95 thing and we would be better off not relying
on it. AFAICS, rw_snprintf() is only being used in exec.cpp (so
the macro shouldn't be defined in a header) and it should be both
easy and safe to replace it with sprintf.

+*/
+#if !defined (_WIN32) && !defined (_WIN64)
+#  define rw_snprintf snprintf
+#else
+#  define rw_snprintf _snprintf
+#endif
+
+/**
    Generates a non-terminal error message on stderr.
@param format printf () format string to display on stderr
@@ -52,4 +61,24 @@
void* guarded_realloc (void* source, const size_t size, const char* const file, const unsigned line); +/** + Generates the name of a reference (input/output) file, based on dir and mode.
+
+   This function allocates memory which is to be freed by the caller.
+
+   @param dir example subdirectory to reference
+ @param mode type of file to generate name for (should be 'in' or 'out')
+   @return translation of 'in_root/dir/mode/target_name.mode'
+*/
+char* reference_name(const char* dir, const char* mode);

Could you please try to more consistently follow the formatting
conventions I outlined in http://tinyurl.com/mmqgv (specifically
2. bullet 5 :) Thanks!

+
+/**
+   Generates the name of the output file for the executable target.
+
+   This function allocates memory which is to be freed by the caller.
+
+   @param path of target to generate output name for
+   @return translation of 'target.out'
+*/
+char* output_name(const char* target);

Same here: missing space before the opening parenthesis.

 #endif   // RW_UTIL_H
Index: exec.cpp
===================================================================
--- exec.cpp    (revision 430088)
+++ exec.cpp    (working copy)
@@ -37,10 +37,15 @@
[...]
 #include <sys/stat.h> /* for S_* */

FWIW, comments like the one above aren't terribly helpful. I would
suggest to name the first in a series or related symbols and append
an ellipsis to indicate that other related symbols from the header
might be needed.

[...]
@@ -350,10 +355,11 @@
     }
/* We've run out of known signal numbers, so use a default name */
-    snprintf (def, sizeof def, "SIG#%d", signo);
+    rw_snprintf (def, sizeof def, "SIG#%d", signo);

Given a large enough buffer we don't need to worry about overflow
here since we know the maximum length of the string.

[..]
@@ -727,3 +721,216 @@
[...]
+static HANDLE
+open_input (const char* exec_name, SECURITY_ATTRIBUTES* child_sa)

Do we actually use these security attributes for anything? I didn't
look very carefully but it seems to me that we're just passing the
thing around w/o ever using it for anything. Or did I miss something?

[...]
+struct exec_attrs +exec_file (char** argv)
+{
+    char* merged = merge_argv(argv);
[...]
+ context.hStdOutput = CreateFile (tmp_name, GENERIC_WRITE, + FILE_SHARE_WRITE, &child_sa, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL);
+        if (INVALID_HANDLE_VALUE == context.hStdOutput)
+ {

The brace goes on the line above (here and everywhere else).

+            status.status = -1;
+            status.error = GetLastError ();
+            return status;

This looks like a memory leak -- the merged pointer is not freed
before returning.

+        }
+
+        context.hStdError = context.hStdOutput;
+        free (tmp_name);
+
+        /* Input redirection */
+        context.hStdInput = open_input (target_name, &child_sa);
+        if (INVALID_HANDLE_VALUE == context.hStdInput)
+        { +            status.status = -1;
+            status.error = GetLastError ();
+            return status;

Same here.

+        }
+    }    +
+    /* Create the child process */
+ CreateProcess (argv[0], merged, 0, 0, 1, + DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, 0, 0, &context, &child);

Should we be handling errors from CreateProcess?

+
+    /* Clean up handles */
+    CloseHandle(context.hStdInput);
+    CloseHandle(context.hStdOutput);

And issue warnings when these fail? (We should if we do it on the
UNIX side.)

+
+    /* Clean up argument string*/
+    free (merged);
+
+    /* Wait for the child process to terminate */
+ if(WAIT_OBJECT_0 == WaitForSingleObject (child.hProcess, (timeout > 0) ? timeout * 1000 : INFINITE)) {

I would suggest to break out the conditional expression into a separate
statement and reducing the length of the line below 79 characters for
readability.

+        GetExitCodeProcess (child.hProcess, &status.status);
+        status.error = 0;
+        return status;
+    }    +
+ {/* Try to soft kill child process group if it didn't terminate, but only on NT */
+        OSVERSIONINFO OSVer;
+        OSVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+        GetVersionEx (&OSVer);
+        if(VER_PLATFORM_WIN32_NT == OSVer.dwPlatformId) {

Space after if please (same below).

+            GenerateConsoleCtrlEvent (CTRL_C_EVENT, child.dwProcessId);
+ if(WAIT_OBJECT_0 == WaitForSingleObject (child.hProcess, 1000)) {
+                GetExitCodeProcess (child.hProcess, &status.status);
+                status.error = 1;
+                return status;
+            }
+ GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, child.dwProcessId); + if(WAIT_OBJECT_0 == WaitForSingleObject (child.hProcess, 1000)) {
+                GetExitCodeProcess (child.hProcess, &status.status);
+                status.error = 2;
+                return status;
+            }
+        }
+    }
+    /* Then hard kill the child process */
+    TerminateProcess (child.hProcess, 3);

Check if TerminateProcess succeeded?

[...]
Index: cmdopt.cpp
[...]
@@ -84,6 +88,43 @@
     "  '--option=value' or '--option value'.\n"
 };
+#if !defined (_WIN32) && !defined (_WIN64)
+const char escape_code = '\\';
+const char default_path_sep = '//';

Is it safe to assume that the path separator is always one char
long? (It might be, but I'm not sure. It seems the code would
be more robust if we avoided making the assumption.)

[...]
Index: output.cpp
===================================================================
--- output.cpp    (revision 430088)
+++ output.cpp    (working copy)
@@ -233,8 +233,7 @@
 {
     struct stat file_info;
     const size_t root_len = strlen (in_root);
- char* const ref_name = (char*)RW_MALLOC (root_len - + strlen (target_name) + 19);
+    char* ref_name;
     FILE* reference;
assert (0 != in_root);
@@ -243,10 +242,7 @@
     assert (0 != output);
/* Try in_root/manual/out/target_name.out */
-    memcpy (ref_name, in_root, root_len+1);
-    strcat (ref_name, "/manual/out/");
-    strcat (ref_name, target_name);
-    strcat (ref_name, ".out");
+    ref_name = reference_name("manual", "out");
if (0 > stat (ref_name, &file_info)) {

FYI: apparently, there is no native stat on z/OS (see STDCXX-265:
http://issues.apache.org/jira/browse/STDCXX-265). We need to start
thinking about abstracting this to its own function that can be
implemented in terms of, say, fopen() on z/OS.

[...]
+char*
+reference_name(const char* dir, const char* mode)
+{
+    const size_t root_len = strlen (in_root);
+    const size_t cmp_len = strlen (target_name) - exe_suffix_len;
+    const size_t dir_len = strlen (dir);
+    const size_t mode_len = strlen (mode);

We should assert the preconditions of the function before we make
any assumptions about them.

+ char* const ref_name = (char*)RW_MALLOC (root_len + cmp_len + dir_len + + mode_len * 2 + 5);

I suggest to precompute the size of the array and saving it in
a local variable rather than computing it in the argument.

[...]
+    *(tail++) = default_path_sep;

There is no need to parenthesize *(tail++): the expression has the
same meaning without the parentheses and it's so well-established
that using the parentheses will only be confusing.

+    memcpy (tail , dir, dir_len);
+    tail += dir_len;
+    *(tail++) = default_path_sep;
+    memcpy (tail , mode, mode_len);
+    tail += mode_len;
+    *(tail++) = default_path_sep;
+    memcpy (tail , target_name, cmp_len);
+    tail += cmp_len;
+    *(tail++) = '.';

I think z/OS uses a period as the directory separator so if that's
true we should be prepared to avoid using it here...

[...]
+char*
+output_name(const char* target)
+{
+    const char* suffix = ".out";

...as well as here. Again, check with Scott Zhong, our z/OS guru,
about this. (This is just a to-do item and shouldn't hold up your
patch).

[...]
Index: exec.h
===================================================================
--- exec.h    (revision 430088)
+++ exec.h    (working copy)
@@ -28,8 +28,14 @@
 #define RW_EXEC_H
struct exec_attrs {
+#if !defined (_WIN32) && !defined (_WIN64)
     int status;
     int killed;
+#else
+    /* AKA DWORD */

Won't defining status to a different type on different platforms
cause problems (e.g., warnings)? I would suggest to keep them
the same, especially given that they are the same size.

+    unsigned long status;
+    unsigned long error;
+#endif  /* _WIN{32,64} */
 };
int get_signo (const char* signame);
[...]
Index: runall.cpp
[...]
@@ -281,6 +314,7 @@
     if (0 == result->status) {
         parse_output (target);
     } +#if !defined (_WIN32) && !defined (_WIN64)

I wonder if replacing the above with

    #if defined (WIFEXITED)

would make the code more robust.

[...]
@@ -329,9 +371,13 @@
assert (0 != path); - for (mark = pos = path; '\0' != *pos; ++pos)
+    for (mark = pos = path; '\0' != *pos; ++pos) {
+#if !defined (_WIN32) && !defined (_WIN64)
+        mark = (default_path_sep == *pos) ? pos + 1 : mark;
+#else
         mark = ('/' == *pos || '\\' == *pos) ? pos + 1 : mark;

Should we be checking for equality to path_sep here instead of
hardcoding backslash (I know they are the same but just for
consistency).

Martin
Index: util.h
===================================================================
--- util.h	(revision 430520)
+++ util.h	(working copy)
@@ -52,4 +52,24 @@
 void* guarded_realloc (void* source, const size_t size, 
                        const char* const file, const unsigned line);
 
+/**
+   Generates the name of a reference (input/output) file, based on dir and mode.
+
+   This function allocates memory which is to be freed by the caller.
+
+   @param dir example subdirectory to reference
+   @param mode type of file to generate name for (should be 'in' or 'out')
+   @return translation of 'in_root/dir/mode/target_name.mode'
+*/
+char* reference_name(const char* dir, const char* mode);
+
+/**
+   Generates the name of the output file for the executable target.
+
+   This function allocates memory which is to be freed by the caller.
+
+   @param path of target to generate output name for
+   @return translation of 'target.out'
+*/
+char* output_name(const char* target);
 #endif   // RW_UTIL_H
Index: exec.cpp
===================================================================
--- exec.cpp	(revision 430520)
+++ exec.cpp	(working copy)
@@ -341,7 +341,7 @@
 get_signame (int signo)
 {
     size_t i;
-    static char def [16];
+    static char def [32];
 
     for (i = 0; signal_names [i].str; ++i) {
         if (signal_names [i].val == signo) {
@@ -350,7 +350,7 @@
     }
 
     /* We've run out of known signal numbers, so use a default name */
-    snprintf (def, sizeof def, "SIG#%d", signo);
+    sprintf (def, "SIG#%d", signo);
     return def;
 }
 
@@ -535,22 +535,19 @@
 static int
 open_input (const char* exec_name)
 {
-    const size_t root_len = strlen (in_root);
+    size_t root_len;
     int intermit = -1;
 
     assert (0 != exec_name);
     assert (0 != in_root);
 
+    root_len = strlen (in_root);
+
     if (root_len) {
-        const size_t out_len = root_len + strlen (exec_name) + 17;
-    
-        char* const tmp_name = (char*)RW_MALLOC (out_len);
+        char* tmp_name;
 
         /* Try in_root/manual/in/exec_name.in */
-        memcpy (tmp_name, in_root, root_len+1);
-        strcat (tmp_name, "/manual/in/");
-        strcat (tmp_name, exec_name);
-        strcat (tmp_name, ".in");
+        tmp_name = reference_name("manual", "in");
         intermit = open (tmp_name, O_RDONLY);
     
         /* If we opened the file, return the descriptor */
@@ -565,10 +562,8 @@
                        strerror (errno));
 
         /* Try in_root/tutorial/in/exec_name.in */
-        memcpy (tmp_name, in_root, root_len+1);
-        strcat (tmp_name, "/tutorial/in/");
-        strcat (tmp_name, exec_name);
-        strcat (tmp_name, ".in");
+        free (tmp_name);
+        tmp_name = reference_name("tutorial", "in");
         intermit = open (tmp_name, O_RDONLY);
 
         /* If we opened the file, return the descriptor */
@@ -683,14 +678,9 @@
 
         /* Redirect stdout */
         {
-            const size_t exelen = strlen (argv [0]);
-            const size_t outlen = exelen + 5;
-            char* const tmp_name = (char*)RW_MALLOC (outlen);
+            char* const tmp_name = output_name(argv [0]);
             int intermit;
 
-            /* Redirect stdout */
-            memcpy (tmp_name, argv [0], exelen + 1);
-            strcat (tmp_name, ".out");
             intermit = open (tmp_name, O_WRONLY | O_CREAT | O_TRUNC, 
                              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
Index: cmdopt.cpp
===================================================================
--- cmdopt.cpp	(revision 430520)
+++ cmdopt.cpp	(working copy)
@@ -50,6 +50,10 @@
 const char* in_root = ""; /**< Root directory for input/reference files. */
 const char* exe_name; /**< Alias for process argv [0]. */
 const char* target_name;
+const char escape_code = '\\';
+const char default_path_sep = '/';
+const char suffix_sep = '.';
+const size_t exe_suffix_len = 0;
 
 static const char
 usage_text[] = {
@@ -384,10 +388,12 @@
     const char *pos;
     char *target, *last;
     char **table_pos, **argv;
-    const size_t optlen = strlen (opts);
+    size_t optlen;
 
     assert (0 != opts);
 
+    optlen = strlen (opts);
+
     if (0 == optlen) {
         /* Alloc a an index array to hold the program name  */
         argv = (char**)RW_MALLOC (sizeof (char*));
@@ -429,7 +435,7 @@
         }
         in_token = 1;
         switch (*pos) {
-        case '\\':
+        case escape_code:
             in_escape = 1;
             break;
         case '"':
Index: output.cpp
===================================================================
--- output.cpp	(revision 430520)
+++ output.cpp	(working copy)
@@ -232,9 +232,8 @@
 check_example (char* const out_name, FILE* output)
 {
     struct stat file_info;
-    const size_t root_len = strlen (in_root);
-    char* const ref_name = (char*)RW_MALLOC (root_len 
-                                             + strlen (target_name) + 19);
+    size_t root_len;
+    char* ref_name;
     FILE* reference;
 
     assert (0 != in_root);
@@ -242,11 +241,11 @@
     assert (0 != target_name);
     assert (0 != output);
 
+    root_len = strlen (in_root);
+
+
     /* Try in_root/manual/out/target_name.out */
-    memcpy (ref_name, in_root, root_len+1);
-    strcat (ref_name, "/manual/out/");
-    strcat (ref_name, target_name);
-    strcat (ref_name, ".out");
+    ref_name = reference_name("manual", "out");
 
     if (0 > stat (ref_name, &file_info)) {
         if (ENOENT != errno) {
@@ -259,10 +258,8 @@
                         
         /* If that doesn't exist, try 
            in_root/tutorial/out/target_name.out */
-        memcpy (ref_name, in_root, root_len+1);
-        strcat (ref_name, "/tutorial/out/");
-        strcat (ref_name, target_name);
-        strcat (ref_name, ".out");
+        free (ref_name);
+        ref_name = reference_name("tutorial", "out");
 
         if (0 > stat (ref_name, &file_info)) {
             if (ENOENT != errno) {
@@ -344,14 +341,12 @@
 void
 parse_output (const char* target)
 {
-    const size_t path_len = strlen (target);
-    char* const out_name = (char*)RW_MALLOC (path_len + 5);
+    char* out_name;
     FILE* data;
 
     assert (0 != target);
+    out_name = output_name(target);
 
-    memcpy (out_name, target, path_len + 1);
-    strcat (out_name,".out");
 
     data = fopen (out_name, "r");
 
Index: util.cpp
===================================================================
--- util.cpp	(revision 430520)
+++ util.cpp	(working copy)
@@ -86,11 +86,13 @@
 void*
 guarded_malloc (const size_t size, const char* const file, const unsigned line)
 {
-    void* const alloc = malloc (size);
+    void* alloc;
 
     assert (0 != file);
     assert (0 < size);
 
+    alloc = malloc (size);
+
     if (0 == alloc)
         terminate (1, "malloc (%lu) at line %u of %s failed: %s\n", 
                  (unsigned long)size, line, file, strerror (errno));
@@ -111,14 +113,70 @@
 guarded_realloc (void* source, const size_t size, const char* const file, 
                  const unsigned line)
 {
-    void* const alloc = realloc (source, size);
+    void* alloc;
 
     assert (0 != file);
     assert (0 < size);
 
+    alloc = realloc (source, size);
+
     if ( 0 == alloc )
         terminate ( 1, "malloc(%lu) at line %u of %s failed: %s\n", 
                  (unsigned long)size, line, file, strerror (errno));
 
     return alloc;
 }
+
+char*
+reference_name (const char* dir, const char* mode)
+{
+    size_t root_len, cmp_len, dir_len, mode_len, net_len;
+    char* ref_name;
+    char* tail;
+
+    assert (0 != in_root);
+    assert (0 != target_name);
+    assert (0 != dir);
+    assert (0 != mode);
+
+    root_len = strlen (in_root);
+    cmp_len = strlen (target_name) - exe_suffix_len;
+    dir_len = strlen (dir);
+    mode_len = strlen (mode);
+    net_len = root_len + cmp_len + dir_len + mode_len * 2 + 5;
+    /* 5 comes from 3 path seperator characters, the suffix seperator 
+       character, and the trailing null */
+    tail = ref_name = (char*)RW_MALLOC (net_len);
+
+    memcpy (tail, in_root, root_len);
+    tail += root_len;
+    *tail++ = default_path_sep;
+    memcpy (tail , dir, dir_len);
+    tail += dir_len;
+    *tail++ = default_path_sep;
+    memcpy (tail , mode, mode_len);
+    tail += mode_len;
+    *tail++ = default_path_sep;
+    memcpy (tail , target_name, cmp_len);
+    tail += cmp_len;
+    *tail++ = suffix_sep;
+    memcpy (tail , mode, mode_len);
+    tail += mode_len;
+    *tail = '\0';
+
+    return ref_name;
+}
+
+char*
+output_name (const char* target)
+{
+    const char* suffix = "out";
+    const size_t sfx_len = strlen (suffix);
+    const size_t exe_len = strlen (target) - exe_suffix_len;
+    char* const tmp_name = (char*)RW_MALLOC (exe_len + sfx_len + 2);
+    
+    memcpy (tmp_name, target, exe_len);
+    *(tmp_name + exe_len) = suffix_sep;
+    memcpy (tmp_name + exe_len + 1, suffix, sfx_len + 1);
+    return tmp_name;
+}
Index: cmdopt.h
===================================================================
--- cmdopt.h	(revision 430520)
+++ cmdopt.h	(working copy)
@@ -34,6 +34,10 @@
 extern const char* in_root;
 extern const char* exe_name;
 extern const char* target_name; /**< Alias for current target name. */
+extern const char escape_code; /**< Escape character used in paths. */
+extern const char default_path_sep; /**< Primary path seperator */
+extern const char suffix_sep; /**< File suffix seperator. */
+extern const size_t exe_suffix_len; /**< Length of executable suffix. */
 
 void 
 show_usage (int status);
Index: runall.cpp
===================================================================
--- runall.cpp	(revision 430520)
+++ runall.cpp	(working copy)
@@ -69,13 +69,17 @@
 static char** const
 merge_argv (char* const target, char* const argv [])
 {
-    const size_t tlen = strlen (target);
-    char ** split = split_opt_string (target);
+    size_t tlen;
+    char ** split;
     unsigned i, arg_count = 0, spl_count = 0, wld_count = 0;
 
     assert (0 != target);
     assert (0 != argv);
 
+    tlen = strlen (target);
+    split = split_opt_string (target);
+
+
     /* If the split of target only contains a single value, we may have a 
      bare executable name */
     if (!split [1]) {
@@ -211,6 +215,7 @@
         const size_t path_len = strlen (target);
         char* tmp_name;
 
+#if 0 /* Disable .o target check as unused */
         /* If target is a .o file, check if it exists */
         if ('.' == target [path_len-1] && 'o' == target [path_len]) {
             if (exists)
@@ -219,6 +224,7 @@
                 puts ("  COMP");
             return 0;
         }
+#endif
             
         /* If the target exists, it doesn't have valid permissions */
         if (exists) {
@@ -330,7 +336,7 @@
     assert (0 != path);
 
     for (mark = pos = path; '\0' != *pos; ++pos)
-        mark = ('/' == *pos || '\\' == *pos) ? pos + 1 : mark;
+        mark = (default_path_sep == *pos) ? pos + 1 : mark;
 
     return mark;
 }
@@ -352,11 +358,15 @@
 run_target (char* target, char** argv)
 {
     struct exec_attrs status;
-    char** childargv = merge_argv (target, argv);
+    char** childargv;
 
     assert (0 != target);
     assert (0 != argv);
+
+    childargv = merge_argv (target, argv);
+
     assert (0 != childargv);
+    assert (0 != childargv[0]);
 
     target_name = rw_basename (childargv [0]);
 

Reply via email to