]> granicus.if.org Git - yasm/commitdiff
vsyasm: create intermediate output directories if necessary.
authorPeter Johnson <peter@tortall.net>
Sat, 13 Feb 2010 08:42:27 +0000 (08:42 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 13 Feb 2010 08:42:27 +0000 (08:42 -0000)
This feature is apparently assumed by MSBUILD.

Contributed (with minor modifications) by: Brian Gladman

svn path=/trunk/yasm/; revision=2287

configure.ac
frontends/vsyasm/vsyasm.c
libyasm/file.c
libyasm/file.h

index 501b7525837be4ae928138a7796fa9f29c597550..638d654aae22b4017740ae2517d9b562a5086919 100644 (file)
@@ -105,7 +105,7 @@ AM_WITH_DMALLOC
 # Checks for header files.
 #
 AC_HEADER_STDC
-AC_CHECK_HEADERS([strings.h libgen.h unistd.h direct.h])
+AC_CHECK_HEADERS([strings.h libgen.h unistd.h direct.h sys/stat.h])
 
 # REQUIRE standard C headers
 if test "$ac_cv_header_stdc" != yes; then
index 43a478d8d238f33a04ff480530d16879e0419a35..5983a954bd8ba05e0afd2b43d6367868990e87e5 100644 (file)
@@ -45,7 +45,8 @@
 #include "license.c"
 
 /*@null@*/ /*@only@*/ static char *objdir_pathname = NULL;
-/*@null@*/ /*@only@*/ static char *global_prefix = NULL, *global_suffix = NULL;
+/*@null@*/ /*@only@*/ static char *global_prefix = NULL, *global_suffix =
+NULL;
 /*@null@*/ /*@only@*/ static char *listdir_pathname = NULL;
 /*@null@*/ /*@only@*/ static char *mapdir_pathname = NULL;
 /*@null@*/ /*@only@*/ static char *machine_name = NULL;
@@ -658,6 +659,20 @@ main(int argc, char *argv[])
     /* If not already specified, output to the current directory. */
     if (!objdir_pathname)
         objdir_pathname = yasm__xstrdup("./");
+    else if((i = yasm__createpath(objdir_pathname)) > 0) {
+        objdir_pathname[i] = '/';
+        objdir_pathname[i+1] = '\0';
+    }
+
+    /* Create other output directories if necessary */
+    if (listdir_pathname && (i = yasm__createpath(listdir_pathname)) > 0) {
+        listdir_pathname[i] = '/';
+        listdir_pathname[i+1] = '\0';
+    }
+    if (mapdir_pathname && (i = yasm__createpath(mapdir_pathname)) > 0) {
+        mapdir_pathname[i] = '/';
+        mapdir_pathname[i+1] = '\0';
+    }
 
     /* Assemble each input file.  Terminate on first error. */
     STAILQ_FOREACH(infile, &input_files, link)
@@ -927,7 +942,6 @@ opt_listdir_handler(/*@unused@*/ char *cmd, char *param,
     assert(param != NULL);
     listdir_pathname = yasm_xmalloc(strlen(param)+2);
     strcpy(listdir_pathname, param);
-    strcat(listdir_pathname, "/");
 
     return 0;
 }
@@ -945,7 +959,6 @@ opt_objdir_handler(/*@unused@*/ char *cmd, char *param,
     assert(param != NULL);
     objdir_pathname = yasm_xmalloc(strlen(param)+2);
     strcpy(objdir_pathname, param);
-    strcat(objdir_pathname, "/");
 
     return 0;
 }
@@ -963,7 +976,6 @@ opt_mapdir_handler(/*@unused@*/ char *cmd, char *param,
     assert(param != NULL);
     mapdir_pathname = yasm_xmalloc(strlen(param)+2);
     strcpy(mapdir_pathname, param);
-    strcat(mapdir_pathname, "/");
 
     return 0;
 }
index 128934a85e7ec0216f3612aafe8afccd8294cc4c..076093489cf901a19745933d1883c3d812420b05 100644 (file)
 #include <direct.h>
 #endif
 
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
 #include <ctype.h>
 #include <errno.h>
 
@@ -450,6 +458,68 @@ yasm__combpath_win(const char *from, const char *to)
     return out;
 }
 
+size_t
+yasm__createpath_common(const char *path, int win)
+{
+    const char *pp = path, *pe;
+    char *ts, *tp;
+    size_t len, lth;
+
+    lth = len = strlen(path);
+    ts = tp = (char *) malloc(len + 1);
+    pe = pp + len;
+    while (pe > pp) {
+        if ((win && *pe == '\\') || *pe == '/')
+            break;
+        --pe;
+        --lth;
+    }
+
+    while (pp <= pe) {
+        if (pp == pe || (win && *pp == '\\') || *pp == '/') {
+#ifdef _WIN32
+            struct _finddata_t fi; 
+            intptr_t h;
+#elif defined(HAVE_SYS_STAT_H) 
+            struct stat fi;
+#endif
+            *tp = '\0';
+
+#ifdef _WIN32
+            h = _findfirst(ts, &fi);
+            if (h != -1) {
+                if (fi.attrib != _A_SUBDIR) {
+                    _findclose(h);
+                    break;
+                }
+            } else if (errno == ENOENT) {
+                if (_mkdir(ts) == -1) {
+                    _findclose(h);
+                    lth = -1;
+                    break;
+                }
+            }
+            _findclose(h);
+#elif defined(HAVE_SYS_STAT_H)
+            if (stat(ts, &fi) != -1) {
+                if (!S_ISDIR(fi.st_mode))
+                    break;
+            } else if (errno == ENOENT) {
+                if (mkdir(ts, 0755) == -1) {
+                    lth = 0;
+                    break;
+                }
+            }
+#else
+            break;
+#endif
+        }
+        *tp++ = *pp++;
+    }
+    free(ts);
+    return lth;
+}
+
 typedef struct incpath {
     STAILQ_ENTRY(incpath) link;
     /*@owned@*/ char *path;
index a1de0339871b9a73468ac9559cde3c755d2c502c..d99785dd0b89a5ed625067329bae21c8fd7fdc6b 100644 (file)
@@ -179,6 +179,30 @@ char *yasm__combpath_win(const char *from, const char *to);
 # endif
 #endif
 
+/** Recursively create tree of directories needed for pathname.
+ * \internal
+ * \param path  pathname
+ * \param win   handle windows paths
+ * \return Length of directory portion of pathname.
+ */
+YASM_LIB_DECL
+size_t yasm__createpath_common(const char *path, int win);
+
+/** Recursively create tree of directories needed for pathname.
+ * Unless otherwise defined, defaults to yasm__createpath_unix().
+ * \internal
+ * \param path  pathname
+ * \return Length of directory portion of pathname.
+ */
+#ifndef yasm__createpath
+# if defined (_WIN32) || defined (WIN32) || defined (__MSDOS__) || \
+ defined (__DJGPP__) || defined (__OS2__)
+#  define yasm__createpath(path)    yasm__createpath_common(path, 1)
+# else
+#  define yasm__createpath(path)    yasm__createpath_common(path, 0)
+# endif
+#endif
+
 /** Try to find and open an include file, searching through include paths.
  * First iname is looked for relative to the directory containing "from", then
  * it's looked for relative to each of the include paths.