From: Keith Marshall Date: Fri, 3 Aug 2012 22:04:29 +0000 (+0100) Subject: More code refactoring, to facilitate GUI implementation. X-Git-Tag: r0-6-0-beta-20130904-1~66 X-Git-Url: http://git.osdn.net/view?p=mingw%2Fmingw-get.git;a=commitdiff_plain;h=01c16e373c94615e41080c288b650ab55b28fd11 More code refactoring, to facilitate GUI implementation. --- diff --git a/ChangeLog b/ChangeLog index e906588..7d14d02 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2012-08-03 Keith Marshall + + 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 Find missing.m4 in build-aux/m4 directory. diff --git a/Makefile.in b/Makefile.in index 15e9df0..66a90c0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 index 0000000..3407151 --- /dev/null +++ b/src/approot.c @@ -0,0 +1,187 @@ +/* + * approot.c + * + * $Id$ + * + * Written by Keith Marshall + * 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 +#include +#include +#include +#include + +#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 index 0000000..09e802b --- /dev/null +++ b/src/approot.h @@ -0,0 +1,40 @@ +#ifndef APPROOT_H +/* + * approot.h + * + * $Id$ + * + * Written by Keith Marshall + * 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 */ diff --git a/src/clistub.c b/src/clistub.c index dc2cc51..0ef35a0 100644 --- a/src/clistub.c +++ b/src/clistub.c @@ -28,6 +28,7 @@ #define WIN32_LEAN_AND_MEAN #include "debug.h" +#include "approot.h" #include #include @@ -41,123 +42,6 @@ #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 ); } diff --git a/src/rites.c b/src/rites.c index dbfc403..97e3e51 100644 --- a/src/rites.c +++ b/src/rites.c @@ -39,6 +39,10 @@ #include #include +/* 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"