Improved portability on Cygwin and DJGPP.

git-svn-id: svn://svn.code.sf.net/p/ctags/code/trunk@307 c5d04d22-be80-434c-894e-aa346cc9e8e8
This commit is contained in:
darren 2003-03-31 04:53:22 +00:00
parent e63bb29d62
commit 0a2de495a5
8 changed files with 216 additions and 160 deletions

View File

@ -9,7 +9,7 @@ For non-Unix platforms, simple makefiles are provided:
descrip.mms For VMS using either DEC C or VAX C descrip.mms For VMS using either DEC C or VAX C
mk_bc3.mak For MSDOS using Borland C/C++ 3.x mk_bc3.mak For MSDOS using Borland C/C++ 3.x
mk_bc5.mak For Win32 using Borland C++ 5.5 mk_bc5.mak For Win32 using Borland C++ 5.5
mk_djg.mak For MSDOS using Gnu GCC (DJGPP) mk_djg.mak For MSDOS using DJGPP Gnu GCC (better to follow Unix install)
mk_manx.mak For Amiga using Aztec/Manx C 5.0 mk_manx.mak For Amiga using Aztec/Manx C 5.0
mk_ming.mak For Win32 using Mingw32 mk_ming.mak For Win32 using Mingw32
mk_mpw.mak For Macintosh using MPW mk_mpw.mak For Macintosh using MPW
@ -34,6 +34,12 @@ Win32:
See the makefiles, mk_mvc.mak or mk_bc5.mak, to learn how to build with See the makefiles, mk_mvc.mak or mk_bc5.mak, to learn how to build with
this library. this library.
DJGPP:
------
It is better to follow the standard Unix install on DJGPP, but this requires
that you use BASH and requires a fairly complete installation of GJGPP
packages. You can use mk_djg.mak if you can't run configure.
Macintosh with MPW: Macintosh with MPW:
------------------- -------------------

3
NEWS
View File

@ -1,6 +1,6 @@
Current Version: @@VERSION@@ Current Version: @@VERSION@@
ctags-5.5 (Sat Mar 29 2003) ctags-5.5 (Sun Mar 30 2003)
* Changed kind indicator for methods from 'f' to 'm' [Tcl]. * Changed kind indicator for methods from 'f' to 'm' [Tcl].
* Changed tags within interfaces to be disabled by default (like prototypes in * Changed tags within interfaces to be disabled by default (like prototypes in
C/C++) [Fortran]. C/C++) [Fortran].
@ -42,6 +42,7 @@ ctags-5.5 (Sat Mar 29 2003)
* Fixed man page errors and omissions. * Fixed man page errors and omissions.
* Fixed bug in readFieldValue() in readtags library. * Fixed bug in readFieldValue() in readtags library.
* Fixed bug in option parsing in readtags command-line program. * Fixed bug in option parsing in readtags command-line program.
* Fixed portability problems with Cygwin and DJGPP.
ctags-5.4 (Thu Oct 17 2002) ctags-5.4 (Thu Oct 17 2002)
* Improved ability for tagsOpen() in readtags library to report failure to * Improved ability for tagsOpen() in readtags library to report failure to

View File

@ -71,6 +71,10 @@ AC_ARG_ENABLE(maintainer-mode,
[ --enable-maintainer-mode [ --enable-maintainer-mode
use maintainer makefile]) use maintainer makefile])
AC_ARG_ENABLE(shell-globbing,
[ --enable-shell-globbing=DIR
does shell expand wildcards (yes|no)? [yes]])
AC_ARG_ENABLE(tmpdir, AC_ARG_ENABLE(tmpdir,
[ --enable-tmpdir=DIR default directory for temporary files [ARG=/tmp]], [ --enable-tmpdir=DIR default directory for temporary files [ARG=/tmp]],
tmpdir_specified=yes) tmpdir_specified=yes)
@ -112,31 +116,6 @@ if test "$enable_macro_patterns" = yes ; then
AC_MSG_RESULT(tag file will use patterns for macros by default) AC_MSG_RESULT(tag file will use patterns for macros by default)
fi fi
AC_MSG_CHECKING(selected sort method)
if test no = "$enable_external_sort"; then
AC_MSG_RESULT(simple internal algorithm)
else
AC_MSG_RESULT(external sort utility)
enable_external_sort=no
AC_CHECK_PROG(sort_found, sort, yes, no)
if test "$sort_found" = yes ; then
AC_MSG_CHECKING(if sort accepts our command line)
touch /tmp/sort.test
sort -u -f -o /tmp/sort.test /tmp/sort.test 1>/dev/null 2>&1
if test $? -ne 0 ; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT(yes)
AC_DEFINE(EXTERNAL_SORT)
enable_external_sort=yes
fi
rm -f /tmp/sort.test
fi
fi
if test "$enable_external_sort" != yes ; then
AC_MSG_RESULT(using internal sort algorithm as fallback)
fi
dnl Checks for programs dnl Checks for programs
dnl ------------------- dnl -------------------
@ -172,6 +151,30 @@ AC_CHECK_PROG(STRIP, strip, strip, :)
dnl Checks for operating environment dnl Checks for operating environment
dnl -------------------------------- dnl --------------------------------
dnl Check for temporary directory
AC_MSG_CHECKING(directory to use for temporary files)
if test -n "$enable_tmpdir"; then
tmpdir="$enable_tmpdir"
elif test -n "$TMPDIR"; then
tmpdir="$TMPDIR"
elif test -n "$TMPDIR"; then
tmpdir="$TMPDIR"
elif test -n "$TMP"; then
tmpdir="$TMP"
elif test -n "$TEMP"; then
tmpdir="$TEMP"
elif test -d "c:/"; then
tmpdir="c:/"
else
tmpdir="/tmp"
fi
if test -d $tmpdir ; then
AC_MSG_RESULT($tmpdir)
AC_DEFINE_UNQUOTED(TMPDIR, "$tmpdir")
else
AC_MSG_ERROR($tmpdir does not exist)
fi
dnl Check whether system supports #! scripts dnl Check whether system supports #! scripts
AC_SYS_INTERPRETER AC_SYS_INTERPRETER
if test yes = "$interpval"; then if test yes = "$interpval"; then
@ -189,6 +192,31 @@ else
fi fi
rm -f conftest.cif rm -f conftest.cif
AC_MSG_CHECKING(selected sort method)
if test no = "$enable_external_sort"; then
AC_MSG_RESULT(simple internal algorithm)
else
AC_MSG_RESULT(external sort utility)
enable_external_sort=no
AC_CHECK_PROG(sort_found, sort, yes, no)
if test "$sort_found" = yes ; then
AC_MSG_CHECKING(if sort accepts our command line)
touch ${tmpdir}/sort.test
sort -u -f -o ${tmpdir}/sort.test ${tmpdir}/sort.test 1>/dev/null 2>&1
if test $? -ne 0 ; then
AC_MSG_RESULT(no)
else
AC_MSG_RESULT(yes)
AC_DEFINE(EXTERNAL_SORT)
enable_external_sort=yes
fi
rm -f ${tmpdir}/sort.test
fi
fi
if test "$enable_external_sort" != yes ; then
AC_MSG_RESULT(using internal sort algorithm as fallback)
fi
dnl Checks for header files dnl Checks for header files
dnl ----------------------- dnl -----------------------
@ -276,21 +304,10 @@ if test "$have_mkstemp" != yes -a "$have_tempnam" != yes; then
if test "$tmpdir_specified" = yes ; then if test "$tmpdir_specified" = yes ; then
AC_MSG_RESULT(use of tmpnam overrides temporary directory selection) AC_MSG_RESULT(use of tmpnam overrides temporary directory selection)
fi fi
else
AC_MSG_CHECKING(directory to use for temporary files)
if test -z "$enable_tmpdir" -o "$enable_tmpdir" = no -o "$enable_tmpdir" = yes ;
then tmpdir=/tmp
else tmpdir="$enable_tmpdir"
fi
if test -d $tmpdir ; then
AC_MSG_RESULT($tmpdir)
AC_DEFINE_UNQUOTED(TMPDIR, "$tmpdir")
else
AC_MSG_WARN($tmpdir does not exist)
fi
fi fi
AC_CHECK_FUNCS(strerror opendir) AC_CHECK_FUNCS(opendir findfirst _findfirst, break)
AC_CHECK_FUNCS(strerror)
AC_CHECK_FUNCS(clock times, break) AC_CHECK_FUNCS(clock times, break)
AC_CHECK_FUNCS(remove, have_remove=yes, AC_CHECK_FUNCS(remove, have_remove=yes,
CHECK_HEADER_DEFINE(remove, unistd.h,, AC_DEFINE(remove, unlink))) CHECK_HEADER_DEFINE(remove, unistd.h,, AC_DEFINE(remove, unlink)))

View File

@ -13,12 +13,34 @@
#define CASE_INSENSITIVE_FILENAMES 1 #define CASE_INSENSITIVE_FILENAMES 1
#define MSDOS_STYLE_PATH 1 #define MSDOS_STYLE_PATH 1
#define HAVE_DIR_H 1
#define HAVE_DIRENT_H 1
#define HAVE_FCNTL_H 1
#define HAVE_FNMATCH_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_DIR_H 1
#define HAVE_SYS_STAT_H 1 #define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIMES_H 1
#define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_TYPES_H 1
#define HAVE_TIME_H 1
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 1
#define HAVE_CLOCK 1
#define HAVE_FGETPOS 1 #define HAVE_FGETPOS 1
#define HAVE_FINDFIRST 1 #define HAVE_FNMATCH 1
#define HAVE_MKSTEMP 1
#define HAVE_OPENDIR 1
#define HAVE_REGCOMP 1
#define HAVE_REMOVE 1
#define HAVE_SETENV 1
#define HAVE_STAT_ST_INO 1
#define HAVE_STRCASECMP 1
#define HAVE_STRERROR 1
#define HAVE_STRNCASECMP 1
#define HAVE_STRSTR 1
#define HAVE_TRUNCATE 1 #define HAVE_TRUNCATE 1
#define NEED_PROTO_LSTAT 1
#define STDC_HEADERS 1
#endif #endif

View File

@ -17,6 +17,7 @@
#define errout stdout #define errout stdout
#define CASE_INSENSITIVE_FILENAMES 1 #define CASE_INSENSITIVE_FILENAMES 1
#define MANUAL_GLOBBING 1
#define MSDOS_STYLE_PATH 1 #define MSDOS_STYLE_PATH 1
#define HAVE_DOS_H 1 #define HAVE_DOS_H 1
#define HAVE_FCNTL_H 1 #define HAVE_FCNTL_H 1

View File

@ -85,14 +85,6 @@
# endif # endif
#endif #endif
#ifndef HAVE_STRICMP
# define stricmp(s1,s2) struppercmp(s1,s2)
#endif
#ifndef HAVE_STRICMP
# define strnicmp(s1,s2,n) strnuppercmp(s1,s2,n)
#endif
/* /*
* DATA DECLARATIONS * DATA DECLARATIONS
*/ */

230
main.c
View File

@ -236,93 +236,110 @@ static boolean excludedFile (const char* const name)
return result; return result;
} }
# if defined (MSDOS) || defined (WIN32) #if defined (HAVE_OPENDIR)
static boolean recurseUsingOpendir (const char *const dirName)
static boolean createTagsForMatchingEntries (char *const pattern)
{ {
boolean resize = FALSE; boolean resize = FALSE;
const size_t dirLength = baseFilename (pattern) - (char *) pattern; DIR *const dir = opendir (dirName);
vString *const filePath = vStringNew (); if (dir == NULL)
error (WARNING | PERROR, "cannot recurse into directory \"%s\"", dirName);
else
{
struct dirent *entry;
while ((entry = readdir (dir)) != NULL)
{
if (strcmp (entry->d_name, ".") != 0 &&
strcmp (entry->d_name, "..") != 0)
{
vString *filePath;
if (strcmp (dirName, ".") == 0)
filePath = vStringNewInit (entry->d_name);
else
filePath = combinePathAndFile (dirName, entry->d_name);
resize |= createTagsForEntry (vStringValue (filePath));
vStringDelete (filePath);
}
}
closedir (dir);
}
return resize;
}
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
static boolean createTagsForWildcardEntry (
const char *const pattern, const size_t dirLength,
const char *const entryName)
{
boolean resize = FALSE;
/* we must not recurse into the directories "." or ".." */
if (strcmp (entryName, ".") != 0 && strcmp (entryName, "..") != 0)
{
vString *const filePath = vStringNew ();
vStringNCopyS (filePath, pattern, dirLength);
vStringCatS (filePath, entryName);
resize = createTagsForEntry (vStringValue (filePath));
vStringDelete (filePath);
}
return resize;
}
static boolean createTagsForWildcardUsingFindfirst (const char *const pattern)
{
boolean resize = FALSE;
const size_t dirLength = baseFilename (pattern) - pattern;
#if defined (HAVE_FINDFIRST) #if defined (HAVE_FINDFIRST)
struct ffblk fileInfo; struct ffblk fileInfo;
int result = findfirst (pattern, &fileInfo, FA_DIREC); int result = findfirst (pattern, &fileInfo, FA_DIREC);
while (result == 0) while (result == 0)
{ {
const char *const entryName = fileInfo.ff_name; const char *const entry = (const char *) fileInfo.ff_name;
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
/* We must not recurse into the directories "." or "..".
*/
if (strcmp (entryName, ".") != 0 && strcmp (entryName, "..") != 0)
{
vStringNCopyS (filePath, pattern, dirLength);
vStringCatS (filePath, entryName);
resize |= createTagsForEntry (vStringValue (filePath));
}
result = findnext (&fileInfo); result = findnext (&fileInfo);
} }
#elif defined (HAVE__FINDFIRST) #elif defined (HAVE__FINDFIRST)
struct _finddata_t fileInfo; struct _finddata_t fileInfo;
long hFile = _findfirst (pattern, &fileInfo); intptr_t hFile = _findfirst (pattern, &fileInfo);
if (hFile != -1L) if (hFile != -1L)
{ {
do do
{ {
const char *const entryName = fileInfo.name; const char *const entry = (const char *) fileInfo.name;
resize |= createTagsForWildcardEntry (pattern, dirLength, entry);
/* We must not recurse into the directories "." or "..".
*/
if (strcmp (entryName, ".") != 0 && strcmp (entryName, "..") != 0)
{
vStringNCopyS (filePath, pattern, dirLength);
vStringCatS (filePath, entryName);
resize |= createTagsForEntry (vStringValue (filePath));
}
} while (_findnext (hFile, &fileInfo) == 0); } while (_findnext (hFile, &fileInfo) == 0);
_findclose (hFile); _findclose (hFile);
} }
#endif #endif
vStringDelete (filePath);
return resize; return resize;
} }
#elif defined (AMIGA) #elif defined (AMIGA)
static boolean createTagsForMatchingEntries (char *const pattern) static boolean createTagsForAmigaWildcard (const char *const pattern)
{ {
boolean resize = FALSE; boolean resize = FALSE;
struct AnchorPath *const anchor = struct AnchorPath *const anchor =
(struct AnchorPath *) eMalloc ((size_t) ANCHOR_SIZE); (struct AnchorPath *) eMalloc ((size_t) ANCHOR_SIZE);
LONG result;
if (anchor != NULL) memset (anchor, 0, (size_t) ANCHOR_SIZE);
{ anchor->ap_Strlen = ANCHOR_BUF_SIZE;
LONG result; /* Allow '.' for current directory */
memset (anchor, 0, (size_t) ANCHOR_SIZE);
anchor->ap_Strlen = ANCHOR_BUF_SIZE; /* ap_Length no longer supported */
/* Allow '.' for current directory.
*/
#ifdef APF_DODOT #ifdef APF_DODOT
anchor->ap_Flags = APF_DODOT | APF_DOWILD; anchor->ap_Flags = APF_DODOT | APF_DOWILD;
#else #else
anchor->ap_Flags = APF_DoDot | APF_DoWild; anchor->ap_Flags = APF_DoDot | APF_DoWild;
#endif #endif
result = MatchFirst ((UBYTE *) pattern, anchor);
result = MatchFirst ((UBYTE *) pattern, anchor); while (result == 0)
while (result == 0) {
{ resize |= createTagsForEntry ((char *) anchor->ap_Buf);
resize |= createTagsForEntry ((char *) anchor->ap_Buf); result = MatchNext (anchor);
result = MatchNext (anchor);
}
MatchEnd (anchor);
eFree (anchor);
} }
MatchEnd (anchor);
eFree (anchor);
return resize; return resize;
} }
#endif #endif
static boolean recurseIntoDirectory (const char *const dirName) static boolean recurseIntoDirectory (const char *const dirName)
@ -334,50 +351,32 @@ static boolean recurseIntoDirectory (const char *const dirName)
verbose ("ignoring \"%s\" (directory)\n", dirName); verbose ("ignoring \"%s\" (directory)\n", dirName);
else else
{ {
#if defined (HAVE_OPENDIR)
DIR *const dir = opendir (dirName);
if (dir == NULL)
error (WARNING | PERROR, "cannot recurse into directory \"%s\"",
dirName);
else
{
struct dirent *entry;
verbose ("RECURSING into directory \"%s\"\n", dirName);
while ((entry = readdir (dir)) != NULL)
{
if (strcmp (entry->d_name, ".") != 0 &&
strcmp (entry->d_name, "..") != 0)
{
vString *filePath;
if (strcmp (dirName, ".") == 0)
filePath = vStringNewInit (entry->d_name);
else
filePath = combinePathAndFile (dirName, entry->d_name);
resize |= createTagsForEntry (vStringValue (filePath));
vStringDelete (filePath);
}
}
closedir (dir);
}
#elif defined (AMIGA) || defined (MSDOS) || defined (WIN32)
vString *const pattern = vStringNew ();
verbose ("RECURSING into directory \"%s\"\n", dirName); verbose ("RECURSING into directory \"%s\"\n", dirName);
# ifdef AMIGA #if defined (HAVE_OPENDIR)
if (*dirName != '\0' && strcmp (dirName, ".") != 0) resize = recurseUsingOpendir (dirName);
#elif defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
{ {
vString *const pattern = vStringNew ();
vStringCopyS (pattern, dirName); vStringCopyS (pattern, dirName);
if (dirName [strlen (dirName) - 1] != '/') vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
vStringPut (pattern, '/'); vStringCatS (pattern, "*.*");
resize = createTagsForWildcardUsingFindfirst (vStringValue (pattern));
vStringDelete (pattern);
} }
vStringCatS (pattern, "#?"); #elif defined (AMIGA)
# else {
vStringCopyS (pattern, dirName); vString *const pattern = vStringNew ();
vStringPut (pattern, OUTPUT_PATH_SEPARATOR); if (*dirName != '\0' && strcmp (dirName, ".") != 0)
vStringCatS (pattern, "*.*"); {
# endif vStringCopyS (pattern, dirName);
resize = createTagsForMatchingEntries (vStringValue (pattern)); if (dirName [strlen (dirName) - 1] != '/')
vStringDelete (pattern); vStringPut (pattern, '/');
#endif /* HAVE_OPENDIR */ }
vStringCatS (pattern, "#?");
resize = createTagsForAmigaWildcard (vStringValue (pattern));
vStringDelete (pattern);
}
#endif
} }
return resize; return resize;
} }
@ -404,6 +403,32 @@ static boolean createTagsForEntry (const char *const entryName)
return resize; return resize;
} }
#ifdef MANUAL_GLOBBING
static boolean createTagsForWildcardArg (const char *const arg)
{
boolean resize = FALSE;
vString *const pattern = vStringNewInit (arg);
char *patternS = vStringValue (pattern);
#if defined (HAVE_FINDFIRST) || defined (HAVE__FINDFIRST)
/* We must transform the "." and ".." forms into something that can
* be expanded by the findfirst/_findfirst functions.
*/
if (Option.recurse &&
(strcmp (patternS, ".") == 0 || strcmp (patternS, "..") == 0))
{
vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
vStringCatS (pattern, "*.*");
}
resize |= createTagsForWildcardUsingFindfirst (patternS);
#endif
vStringDelete (pattern);
return resize;
}
#endif
static boolean createTagsForArgs (cookedArgs* const args) static boolean createTagsForArgs (cookedArgs* const args)
{ {
boolean resize = FALSE; boolean resize = FALSE;
@ -412,23 +437,10 @@ static boolean createTagsForArgs (cookedArgs* const args)
*/ */
while (! cArgOff (args)) while (! cArgOff (args))
{ {
const char *arg = cArgItem (args); const char *const arg = cArgItem (args);
#if defined (MSDOS) || defined (WIN32) #ifdef MANUAL_GLOBBING
vString *const pattern = vStringNewInit (arg); resize |= createTagsForWildcardArg (arg);
char *patternS = vStringValue (pattern);
/* We must transform the "." and ".." forms into something that can
* be expanded by the MSDOS/Windows functions.
*/
if (Option.recurse &&
(strcmp (patternS, ".") == 0 || strcmp (patternS, "..") == 0))
{
vStringPut (pattern, OUTPUT_PATH_SEPARATOR);
vStringCatS (pattern, "*.*");
}
resize |= createTagsForMatchingEntries (patternS);
vStringDelete (pattern);
#else #else
resize |= createTagsForEntry (arg); resize |= createTagsForEntry (arg);
#endif #endif

View File

@ -1,6 +1,11 @@
# $Id$ # $Id$
# #
# The most simplistic Makefile, for DJGPP on MS-DOS # The most simplistic Makefile, for DJGPP Version 2 on Windows
#
# Rather than using this makefile, it is preferable to run "configure", then
# "make" under BASH on DJGPP (i.e. the standard means of building a package on
# Unix), but you have to have a fuller complement of DJGPP packages installed
# to do this.
include source.mak include source.mak