OSDN Git Service

More code refactoring, to facilitate GUI implementation.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Fri, 3 Aug 2012 22:04:29 +0000 (23:04 +0100)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Fri, 3 Aug 2012 22:04:29 +0000 (23:04 +0100)
ChangeLog
Makefile.in
src/approot.c [new file with mode: 0644]
src/approot.h [new file with mode: 0644]
src/clistub.c
src/rites.c

index e906588..7d14d02 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2012-08-03  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       More code refactoring, to facilitate GUI implementation.
+
+       * src/clistub.c (AppPathNameW): Factor out; relocate to...
+       * src/approot.c: ...this new file; it reproduces the original
+       implementation, modified to also consider any "libexec" directory in
+       the executable path as the first child of the APPROOT prefix.  Note
+       also, that no longer terminates APPROOT with a trailing backslash.
+
+       * src/approot.h: New file; it trivially declares the prototype for...
+       (AppPathNameW): ...this relocated extern "C" function.
+
+       * src/clistub.c (main): Adapt usage of AppPathNameW(), to reinstate
+       trailing backslash on assignment to APPROOT environment variable.
+
+       * Makefile.in (CLI_EXE_OBJECTS): New macro; define it as the original
+       set of prerequisites, with the addition of approot.OBJEXT, for...
+       (mingw-get.EXEEXT): ...this; use it.
+
+       * src/rites.c: Add comment regarding APPROOT usage.
+
 2012-08-02  Earnie Boyd  <earnie@users.sourceforge.net>
 
        Find missing.m4 in build-aux/m4 directory.
index 15e9df0..66a90c0 100644 (file)
@@ -66,6 +66,9 @@ CORE_DLL_OBJECTS  =  climain.$(OBJEXT) pkgshow.$(OBJEXT) dmh.$(OBJEXT) \
    tinyxml.$(OBJEXT) tinystr.$(OBJEXT) tinyxmlparser.$(OBJEXT) \
    mkpath.$(OBJEXT)  tinyxmlerror.$(OBJEXT)
 
+CLI_EXE_OBJECTS  =   \
+   clistub.$(OBJEXT) version.$(OBJEXT) approot.$(OBJEXT) getopt.$(OBJEXT)
+
 script_srcdir = ${srcdir}/scripts/libexec
 
 BIN_PROGRAMS = pkginfo$(EXEEXT) mingw-get$(EXEEXT)
@@ -79,7 +82,7 @@ all: $(BIN_PROGRAMS) $(LIBEXEC_PROGRAMS) $(LIBEXEC_DATA)
 pkginfo$(EXEEXT):  driver.$(OBJEXT) pkginfo.$(OBJEXT)
        $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $+
 
-mingw-get$(EXEEXT): clistub.$(OBJEXT) version.$(OBJEXT) getopt.$(OBJEXT)
+mingw-get$(EXEEXT): $(CLI_EXE_OBJECTS)
        $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $+
 
 GUI_LDFLAGS = -mwindows $(LDFLAGS)
diff --git a/src/approot.c b/src/approot.c
new file mode 100644 (file)
index 0000000..3407151
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * approot.c
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2009, 2012, MinGW Project
+ *
+ *
+ * Implementation of helper function to identify the root directory
+ * of the mingw-get installation tree, and to map sub-directory path
+ * names relative to this tree.
+ *
+ *
+ * This is free software.  Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE.  Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+#include <limits.h>
+#include <ctype.h>
+
+#define wcscasecmp _wcsicmp
+
+wchar_t *AppPathNameW( const wchar_t *relpath )
+{
+  /* UTF-16LE implementation; NOT thread safe...
+   *
+   * Map "relpath" into the file system hierarchy with logical root
+   * at the prefix where the application suite is installed, such that
+   * it becomes "d:\prefix\relpath".
+   *
+   * If the application's executables are installed in a directory called
+   * "bin" or "sbin", then this final directory is excluded from the mapped
+   * prefix, (i.e. a program installed as "d:\prefix\bin\prog.exe" returns
+   * the mapped path as "d:\prefix\relpath", rather than as the inclusive
+   * path "d:\prefix\bin\relpath").  Additionally, if the absolute path to
+   * the program executable includes a directory called "libexec", at any
+   * level within the path, then the absolute path to the parent of this is
+   * taken as the effective prefix.  In any other case, the prefix is taken
+   * as the path to the directory in which the program file is installed,
+   * (i.e. a program installed as "d:\prefix\foo\prog.exe" returns the
+   * mapped path as "d:\prefix\foo\relpath".
+   *
+   * Note that, in all cases, the returned path name is normalised, such
+   * that only "\" is used as the directory name separator; this ensures
+   * that it may be safely passed to functions such as LoadLibrary(),
+   * which are known to reject "/" as the separator.
+   *
+   *
+   * Mapped path is returned in this static buffer...
+   */
+  static wchar_t retpath[PATH_MAX], *tail = NULL;
+
+  if( tail == NULL )
+  {
+    /* First time initialisation...
+     *
+     * Fill in the static local buffer, with the appropriate "prefix"
+     * string, marking the point at which "relpath" is to be appended.
+     *
+     * On subsequent calls, we reuse this static buffer, leaving the
+     * "prefix" element unchanged, but simply overwriting the "relpath"
+     * element from any prior call; this is NOT thread safe!
+     */
+    wchar_t bindir[] = L"bin", *bindir_p = bindir;
+    wchar_t *mark, *scan = mark = tail = retpath;
+
+    /* Ascertain the installation path of the calling executable.
+     */
+    int chk = GetModuleFileNameW( NULL, retpath, PATH_MAX );
+
+    /* Validate it; reject any result which doesn't fit in "retpath".
+     */
+    if( (chk == 0) || ((chk == PATH_MAX) && (retpath[--chk] != L'\0')) )
+      return tail = NULL;
+
+    /* Parse it, to locate the end of the effective "prefix" string...
+     */
+    do { if( (*scan == L'/') || (*scan == L'\\') )
+        {
+          /* We found the start of a new path name component directory,
+           * (or maybe the file name, at the end); mark it as a possible
+           * final element of the path name, leaving "tail" pointing to
+           * the previously marked element.
+           */
+          tail = mark;
+          mark = scan;
+          if( scan > tail )
+          {
+            /* The final name element is not empty; temporarily mark
+             * it as "end-of-string", the check if it represents the
+             * "libexec" directory name...
+             */
+            *scan = L'\0';
+            if( wcscasecmp( tail, L"\\libexec" ) == 0 )
+            {
+              /* ...and when it does, we back up to mark its parent
+               * directory as the last in the "prefix" path name...
+               */
+              scan = tail;
+              *scan-- = L'\0';
+            }
+            else
+              /* ...otherwise we append a directory separator, before
+               * cycling around to append the next entity name from the
+               * module path name string.
+               */
+              *scan = L'\\';
+          }
+        }
+       } while( (*++scan) != L'\0' );
+
+    if( *(scan = tail) == L'\\' )
+    {
+      /* When we get to here, "mark" should point to the last directory
+       * separator, immediately preceeding the executable file name, while
+       * "tail" should point to the directory separator preceeding the last
+       * sub-directory name in the path; we now check, without regard to
+       * case, if this final sub-directory name is "bin" or "sbin"...
+       */
+      *mark = L'\0';
+      if( towlower( *++scan ) == L's' )
+       /*
+        * Might be "sbin"; skip the initial "s", and check for "bin"...
+        */
+       ++scan;
+
+      if( wcscasecmp( scan, L"bin" ) == 0 )
+       /*
+        * The final sub-directory is either "bin" or "sbin"; prune it...
+        */
+       *tail = L'\0';
+       /*
+        * ...but when it doesn't match either of these, just adjust the
+        * "tail" pointer, so we leave the final sub-directory name as
+        * part of the "prefix".
+        */
+       tail = mark;
+    }
+  }
+
+  if( relpath == NULL )
+    /*
+     * No "relpath" argument given; simply truncate, to return only
+     * the effective "prefix" string...
+     */
+    *tail = L'\0';
+
+  else
+  { /* We have a "relpath" argument to append; first ensure that the
+     * prefix ends with a directory name separator...
+     */
+    wchar_t *append = tail;
+    if( (*relpath != L'/') && (*relpath != L'\\') )
+      *append++ = L'\\';
+
+    do { /* ...then append the specified path to the application's root,
+         * again, taking care to use "\" as the separator character...
+         */
+        *append++ = (*relpath == L'/') ? L'\\' : *relpath;
+       } while( *relpath++ && ((append - retpath) < PATH_MAX) );
+
+    if( *--append != L'\0' )
+      /*
+       * Abort, if we didn't properly terminate the return string.
+       */
+      return NULL;
+  }
+  return retpath;
+}
+
+/* $RCSfile$: end of file */
diff --git a/src/approot.h b/src/approot.h
new file mode 100644 (file)
index 0000000..09e802b
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef APPROOT_H
+/*
+ * approot.h
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2012, MinGW Project
+ *
+ *
+ * Declaration of the AppPathNameW() function.
+ *
+ *
+ * This is free software.  Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE.  Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#define APPROOT_H  1
+
+#ifndef EXTERN_C
+# ifdef __cplusplus
+#  define EXTERN_C  extern "C"
+# else
+#  define EXTERN_C  extern
+# endif
+#endif
+
+EXTERN_C wchar_t *AppPathNameW( const wchar_t * );
+
+#endif /* APPROOT_H: $RCSfile$: end of file */
index dc2cc51..0ef35a0 100644 (file)
@@ -28,6 +28,7 @@
 #define WIN32_LEAN_AND_MEAN
 
 #include "debug.h"
+#include "approot.h"
 
 #include <windows.h>
 #include <stdio.h>
 #define EXIT_FATAL  EXIT_FAILURE + 1
 
 static const char *progname;
-
-wchar_t *AppPathNameW( const wchar_t *relpath )
-{
-  /* UTF-16LE implementation; NOT thread safe...
-   *
-   * Map "relpath" into the file system hierarchy with logical root
-   * at the prefix where the application suite is installed, such that
-   * it becomes "d:\prefix\relpath".
-   *
-   * If the application's executables are installed in a directory called
-   * "bin" or "sbin", then this final directory is excluded from the mapped
-   * prefix, (i.e. a program installed as "d:\prefix\bin\prog.exe" returns
-   * the mapped path as "d:\prefix\relpath", rather than as the inclusive
-   * path "d:\prefix\bin\relpath"); in any other case, the prefix is taken
-   * as the path to the directory in which the program file is installed,
-   * (i.e. a program installed as "d:\prefix\foo\prog.exe" returns the
-   * mapped path as "d:\prefix\foo\relpath".
-   *
-   * Mapped path is returned in this static buffer...
-   */
-  static wchar_t retpath[MAX_PATH], *tail = NULL;
-
-  if( tail == NULL )
-  {
-    /* First time initialisation...
-     *
-     * Fill in the static local buffer, with the appropriate "prefix"
-     * string, marking the point at which "relpath" is to be appended.
-     *
-     * On subsequent calls, we reuse this static buffer, leaving the
-     * "prefix" element unchanged, but simply overwriting the "relpath"
-     * element from any prior call; this is NOT thread safe!
-     */
-    wchar_t prev = L'\\';
-    wchar_t bindir[] = L"bin", *bindir_p = bindir;
-    wchar_t *mark, *scan = mark = tail = retpath;
-
-    /* Ascertain the installation path of the calling executable.
-     */
-    int chk = GetModuleFileNameW( NULL, retpath, MAX_PATH );
-
-    /* Validate it; reject any result which doesn't fit in "retpath".
-     */
-    if( (chk == 0) || ((chk == MAX_PATH) && (retpath[--chk] != L'\0')) )
-      return tail = NULL;
-
-    /* Parse it, to locate the end of the effective "prefix" string...
-     */
-    do { if( *scan == L'/' )
-          /*
-           * This is a sanity check; it should not be necessary, but...
-           *
-           * Enforce use of "\" rather than "/" as path component separator;
-           * ( "LoadLibrary" may be broken, since it seems to care! )
-           */
-          *scan = L'\\';
-
-        if( *scan && (prev == L'\\') )
-        {
-          /* We found the start a new path name component directory,
-           * (or maybe the file name, at the end); mark it as a possible
-           * final element of the path name, leaving "tail" pointing to
-           * the previously marked element.
-           */
-          tail = mark;
-          mark = scan;
-        }
-       } while( (prev = *scan++) != L'\0' );
-
-    /* When we get to here, "mark" should point to the executable file name,
-     * at the end of the path name string, while "tail" should point to the
-     * last directory in the installation path; we now check, without regard
-     * to case, if this final directory name is "bin" or "sbin"...
-     */
-    if( (*(scan = tail) == L's') || (*scan == L'S') )
-      /*
-       * Might be "sbin"; skip the initial "s", and check for "bin"...
-       */
-      ++scan;
-
-    while( *bindir_p && ((*scan++ | L'\x20') == *bindir_p++) )
-      /*
-       * ...could still match "bin"...
-       */ ;
-    if( *bindir_p || (*scan != L'\\') )
-      /*
-       * No, it didn't match; adjust "tail", so we leave the final
-       * directory name as part of "prefix".
-       */
-      tail = mark;
-  }
-
-  if( relpath == NULL )
-    /*
-     * No "relpath" argument given; simply truncate, to return only
-     * the effective "prefix" string...
-     */
-    *tail = L'\0';
-
-  else
-  { wchar_t *append = tail;
-    do { /*
-         * Append the specified path to the application's root,
-         * again, taking care to use "\" as the separator character...
-         */
-        *append++ = (*relpath == L'/') ? L'\\' : *relpath;
-       } while( *relpath++ && ((append - retpath) < MAX_PATH) );
-
-    if( *--append != L'\0' )
-      /*
-       * Abort, if we didn't properly terminate the return string.
-       */
-      return NULL;
-  }
-  return retpath;
-}
-
 extern const char *version_identification;
 
 static const char *help_text =
@@ -585,10 +469,12 @@ int main( int argc, char **argv )
   if( (approot = AppPathNameW( NULL )) != NULL )
   {
     /* ...and set up the APPROOT environment variable to refer to
-     * the associated installation prefix...
+     * the associated installation prefix, (ensuring that it ends
+     * with a directory name separator)...
      */
-    char approot_setup[1 + snprintf( NULL, 0, "APPROOT=%S", approot )];
-    snprintf( approot_setup, sizeof( approot_setup ), "APPROOT=%S", approot );
+    const char *approot_fmt = "APPROOT=%S\\";
+    char approot_setup[1 + snprintf( NULL, 0, approot_fmt, approot )];
+    snprintf( approot_setup, sizeof( approot_setup ), approot_fmt, approot );
     putenv( approot_setup );
   }
 
index dbfc403..97e3e51 100644 (file)
 #include <stdlib.h>
 #include <errno.h>
 
+/* Path names for supplementary files.  Note that these are relative
+ * to the root of the mingw-get directory tree, as identified by the
+ * $APPROOT environment variable.
+ */
 #define MINGW_GET_EXE  L"bin/mingw-get.exe"
 #define MINGW_GET_LCK  L"var/lib/mingw-get/lock"
 #define MINGW_GET_DLL  L"libexec/mingw-get/mingw-get-0.dll"