From d2c80944d1f27765bea301a9ee1bc023eca9c0f1 Mon Sep 17 00:00:00 2001 From: Kolja Waschk Date: Thu, 3 Apr 2008 20:44:44 +0000 Subject: [PATCH] [ 1916428 ] support runtime-relocatable urjtag (by M.Frysinger) git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1152 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- jtag/ChangeLog | 9 +- jtag/configure.ac | 11 + jtag/include/jtag.h | 2 + jtag/src/bsdl/Makefile.am | 2 - jtag/src/bsdl/bsdl_flex.l | 2 +- jtag/src/cmd/Makefile.am | 5 +- jtag/src/cmd/include.c | 5 +- jtag/src/cmd/jtag_data_dir.c | 39 +++ jtag/src/jtag.c | 6 +- jtag/src/lib/Makefile.am | 12 +- jtag/src/lib/filenames.h | 52 ++++ jtag/src/lib/lbasename.c | 64 +++++ jtag/src/lib/lrealpath.c | 157 +++++++++++ jtag/src/lib/make-relative-prefix.c | 414 ++++++++++++++++++++++++++++ jtag/src/lib/safe-ctype.h | 119 ++++++++ 15 files changed, 888 insertions(+), 11 deletions(-) create mode 100644 jtag/src/cmd/jtag_data_dir.c create mode 100644 jtag/src/lib/filenames.h create mode 100644 jtag/src/lib/lbasename.c create mode 100644 jtag/src/lib/lrealpath.c create mode 100644 jtag/src/lib/make-relative-prefix.c create mode 100644 jtag/src/lib/safe-ctype.h diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 0a5ccbb5..6cb0a6a4 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,8 +1,15 @@ 2008-04-03 Kolja Waschk + * include/jtag.h, src/cmd/jtag_data_dir.c, src/cmd/include.c, + src/cmd/Makefile.am, src/bsdl/Makefile.am, src/bsdl/bsdl_flex.l, + src/lib/make-relative-prefix.c, src/lib/safe-ctype.h, + src/lib/lbasename.c, src/lib/Makefile.am, src/lib/filenames.h, + src/lib/lrealpath.c, src/jtag.c, configure.ac: + [ 1916428 ] support runtime-relocatable urjtag (by Mike Frysinger) + * include/jtag.h, src/cmd/cmd.c, src/cmd/idcode.c, src/cmd/Makefile.am, src/tap/parport/ftdi.c, src/tap/idcode.c, src/tap/Makefile.am, THANKS: - [1933730] new "idcode" command (by U.Bonnes) + [ 1933730 ] new "idcode" command (by Uwe Bonnes) 2008-04-03 Arnim Laeuger diff --git a/jtag/configure.ac b/jtag/configure.ac index 246d4a33..4e0d7885 100644 --- a/jtag/configure.ac +++ b/jtag/configure.ac @@ -517,6 +517,17 @@ CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [ppdev], [ENABLE_PAR CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [ppi], [ENABLE_PARPORT_PPI]) +dnl Enable a relocatable jtag? +AC_ARG_ENABLE(relocatable, +[AS_HELP_STRING([--enable-relocatable], [Enable relocatable paths])], +[relocatable=$enableval], [relocatable=no]) +AS_IF([test "x$relocatable" = xyes], [ + AM_CONDITIONAL(JTAG_RELOCATABLE, true) + AC_DEFINE(JTAG_RELOCATABLE, 1, [define for relocatable paths]) +],[ + AM_CONDITIONAL(JTAG_RELOCATABLE, false) +]) + AC_OUTPUT dnl diff --git a/jtag/include/jtag.h b/jtag/include/jtag.h index d363ffc7..43a9a26b 100644 --- a/jtag/include/jtag.h +++ b/jtag/include/jtag.h @@ -38,6 +38,8 @@ extern bus_t *bus; extern int big_endian; extern int debug_mode; +const char *jtag_get_data_dir( void ); + int jtag_parse_file( chain_t *chain, const char *filename ); int jtag_parse_line( chain_t *chain, char *line ); int jtag_parse_stream( chain_t *chain, FILE *f ); diff --git a/jtag/src/bsdl/Makefile.am b/jtag/src/bsdl/Makefile.am index 8d4dfe86..aa30bccb 100644 --- a/jtag/src/bsdl/Makefile.am +++ b/jtag/src/bsdl/Makefile.am @@ -42,5 +42,3 @@ MAINTAINERCLEANFILES = \ bsdl_bison.c \ bsdl_bison.h \ bsdl_flex.c - -INCLUDES = -DJTAG_DATA_DIR=\"$(pkgdatadir)\" diff --git a/jtag/src/bsdl/bsdl_flex.l b/jtag/src/bsdl/bsdl_flex.l index 7feb387e..0fe357d6 100644 --- a/jtag/src/bsdl/bsdl_flex.l +++ b/jtag/src/bsdl/bsdl_flex.l @@ -495,7 +495,7 @@ void bsdl_flex_switch_file(yyscan_t scanner, char *filename) /* file in current directory has precedence */ f = fopen(filename, "r"); if (!f) { - char db_path[] = JTAG_DATA_DIR; + char *db_path = jtag_get_data_dir(); char *db_file; if ((db_file = (char *)malloc(strlen(db_path) + diff --git a/jtag/src/cmd/Makefile.am b/jtag/src/cmd/Makefile.am index 3dae1fcc..831c6c70 100644 --- a/jtag/src/cmd/Makefile.am +++ b/jtag/src/cmd/Makefile.am @@ -60,7 +60,8 @@ libcmd_a_SOURCES = \ flashmem.c \ eraseflash.c \ include.c \ - cmd.c + cmd.c \ + jtag_data_dir.c if ENABLE_SVF libcmd_a_SOURCES += svf.c @@ -70,4 +71,4 @@ if ENABLE_BSDL libcmd_a_SOURCES += bsdl.c endif -INCLUDES = -DJTAG_DATA_DIR=\"$(pkgdatadir)\" +AM_CPPFLAGS = -DJTAG_BIN_DIR=\"$(bindir)\" -DJTAG_DATA_DIR=\"$(pkgdatadir)\" diff --git a/jtag/src/cmd/include.c b/jtag/src/cmd/include.c index a84b3451..e96c3ede 100644 --- a/jtag/src/cmd/include.c +++ b/jtag/src/cmd/include.c @@ -59,10 +59,11 @@ cmd_include_or_script_run( chain_t *chain, int is_include, char *params[] ) } else { - path = malloc(len = strlen( JTAG_DATA_DIR ) + strlen( params[1] ) + 2); + char *jtag_data_dir = jtag_get_data_dir(); + path = malloc(len = strlen( jtag_data_dir ) + strlen( params[1] ) + 2); if(path != NULL) { - snprintf( path, len, "%s/%s", JTAG_DATA_DIR, params[1] ); + snprintf( path, len, "%s/%s", jtag_data_dir, params[1] ); } } if (path == NULL) { diff --git a/jtag/src/cmd/jtag_data_dir.c b/jtag/src/cmd/jtag_data_dir.c new file mode 100644 index 00000000..89eafea5 --- /dev/null +++ b/jtag/src/cmd/jtag_data_dir.c @@ -0,0 +1,39 @@ +/* + * $Id:$ + * + * Licensed under the GPL-2 or later. + */ + +#include +#include "jtag.h" + +#ifdef JTAG_RELOCATABLE + +#include +#include + +extern char *make_relative_prefix (const char *progname, const char *bin_prefix, const char *prefix); + +extern const char *jtag_argv0; +static char *jtag_data_dir = NULL; + +const char *jtag_get_data_dir(void) +{ + if (jtag_data_dir) + return jtag_data_dir; + + jtag_data_dir = make_relative_prefix(jtag_argv0, JTAG_BIN_DIR, JTAG_DATA_DIR); + if (!jtag_data_dir) + jtag_data_dir = JTAG_DATA_DIR; + + return jtag_data_dir; +} + +#else + +const char *jtag_get_data_dir(void) +{ + return JTAG_DATA_DIR; +} + +#endif diff --git a/jtag/src/jtag.c b/jtag/src/jtag.c index 452ff11f..147f0001 100644 --- a/jtag/src/jtag.c +++ b/jtag/src/jtag.c @@ -253,6 +253,7 @@ cleanup( chain_t *chain ) chain = NULL; } +const char *jtag_argv0; int main( int argc, char *const argv[] ) { @@ -265,11 +266,13 @@ main( int argc, char *const argv[] ) int quiet = 0; chain_t *chain = NULL; + jtag_argv0 = argv[0]; + if(geteuid()==0 && getuid()!=0) { printf (_("'%s' must not be run suid root!\n"), "jtag"); return(-1); - }; + } #ifdef ENABLE_NLS /* l10n support */ @@ -374,7 +377,6 @@ main( int argc, char *const argv[] ) exit(0); } - /* input from files */ if (argc > optind) { for (i = optind; i < argc; i++) { diff --git a/jtag/src/lib/Makefile.am b/jtag/src/lib/Makefile.am index ea264f79..90d0a372 100644 --- a/jtag/src/lib/Makefile.am +++ b/jtag/src/lib/Makefile.am @@ -25,7 +25,17 @@ include $(top_srcdir)/Makefile.rules noinst_LIBRARIES = libjtaglib.a +if JTAG_RELOCATABLE +libiberty_sources = \ + lbasename.c \ + lrealpath.c \ + make-relative-prefix.c +else +libiberty_sources = +endif + libjtaglib_a_SOURCES = \ getdelim.c \ getline.c \ - fclock.c + fclock.c \ + $(libiberty_sources) diff --git a/jtag/src/lib/filenames.h b/jtag/src/lib/filenames.h new file mode 100644 index 00000000..5338208e --- /dev/null +++ b/jtag/src/lib/filenames.h @@ -0,0 +1,52 @@ +/* Macros for taking apart, interpreting and processing file names. + + These are here because some non-Posix (a.k.a. DOSish) systems have + drive letter brain-damage at the beginning of an absolute file name, + use forward- and back-slash in path names interchangeably, and + some of them have case-insensitive file names. + + Copyright 2000, 2001, 2007 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef FILENAMES_H +#define FILENAMES_H + +#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) + +#ifndef HAVE_DOS_BASED_FILE_SYSTEM +#define HAVE_DOS_BASED_FILE_SYSTEM 1 +#endif + +#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\') +/* Note that IS_ABSOLUTE_PATH accepts d:foo as well, although it is + only semi-absolute. This is because the users of IS_ABSOLUTE_PATH + want to know whether to prepend the current working directory to + a file name, which should not be done with a name like d:foo. */ +#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || (((f)[0]) && ((f)[1] == ':'))) + +#else /* not DOSish */ + +#define IS_DIR_SEPARATOR(c) ((c) == '/') +#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0])) + +#endif /* not DOSish */ + +extern int filename_cmp (const char *s1, const char *s2); +#define FILENAME_CMP(s1, s2) filename_cmp(s1, s2) + +#endif /* FILENAMES_H */ diff --git a/jtag/src/lib/lbasename.c b/jtag/src/lib/lbasename.c new file mode 100644 index 00000000..56fcd625 --- /dev/null +++ b/jtag/src/lib/lbasename.c @@ -0,0 +1,64 @@ +/* Libiberty basename. Like basename, but is not overridden by the + system C library. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ + +/* + +@deftypefn Replacement {const char*} lbasename (const char *@var{name}) + +Given a pointer to a string containing a typical pathname +(@samp{/usr/src/cmd/ls/ls.c} for example), returns a pointer to the +last component of the pathname (@samp{ls.c} in this case). The +returned pointer is guaranteed to lie within the original +string. This latter fact is not true of many vendor C +libraries, which return special strings or modify the passed +strings for particular input. + +In particular, the empty string returns the same empty string, +and a path ending in @code{/} returns the empty string after it. + +@end deftypefn + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "ansidecl.h" +#include "libiberty.h" +#include "safe-ctype.h" +#include "filenames.h" + +const char * +lbasename (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over a possible disk name. */ + if (ISALPHA (name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + + return base; +} diff --git a/jtag/src/lib/lrealpath.c b/jtag/src/lib/lrealpath.c new file mode 100644 index 00000000..b27c8de9 --- /dev/null +++ b/jtag/src/lib/lrealpath.c @@ -0,0 +1,157 @@ +/* Libiberty realpath. Like realpath, but more consistent behavior. + Based on gdb_realpath from GDB. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of the libiberty library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* + +@deftypefn Replacement {const char*} lrealpath (const char *@var{name}) + +Given a pointer to a string containing a pathname, returns a canonical +version of the filename. Symlinks will be resolved, and ``.'' and ``..'' +components will be simplified. The returned value will be allocated using +@code{malloc}, or @code{NULL} will be returned on a memory allocation error. + +@end deftypefn + +*/ + +#include "config.h" +#include "ansidecl.h" +#include "libiberty.h" + +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +/* On GNU libc systems the declaration is only visible with _GNU_SOURCE. */ +#if defined(HAVE_CANONICALIZE_FILE_NAME) \ + && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME) +extern char *canonicalize_file_name (const char *); +#endif + +#if defined(HAVE_REALPATH) +# if defined (PATH_MAX) +# define REALPATH_LIMIT PATH_MAX +# else +# if defined (MAXPATHLEN) +# define REALPATH_LIMIT MAXPATHLEN +# endif +# endif +#else + /* cygwin has realpath, so it won't get here. */ +# if defined (_WIN32) +# define WIN32_LEAN_AND_MEAN +# include /* for GetFullPathName */ +# endif +#endif + +char * +lrealpath (const char *filename) +{ + /* Method 1: The system has a compile time upper bound on a filename + path. Use that and realpath() to canonicalize the name. This is + the most common case. Note that, if there isn't a compile time + upper bound, you want to avoid realpath() at all costs. */ +#if defined(REALPATH_LIMIT) + { + char buf[REALPATH_LIMIT]; + const char *rp = realpath (filename, buf); + if (rp == NULL) + rp = filename; + return strdup (rp); + } +#endif /* REALPATH_LIMIT */ + + /* Method 2: The host system (i.e., GNU) has the function + canonicalize_file_name() which malloc's a chunk of memory and + returns that, use that. */ +#if defined(HAVE_CANONICALIZE_FILE_NAME) + { + char *rp = canonicalize_file_name (filename); + if (rp == NULL) + return strdup (filename); + else + return rp; + } +#endif + + /* Method 3: Now we're getting desperate! The system doesn't have a + compile time buffer size and no alternative function. Query the + OS, using pathconf(), for the buffer limit. Care is needed + though, some systems do not limit PATH_MAX (return -1 for + pathconf()) making it impossible to pass a correctly sized buffer + to realpath() (it could always overflow). On those systems, we + skip this. */ +#if defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) + { + /* Find out the max path size. */ + long path_max = pathconf ("/", _PC_PATH_MAX); + if (path_max > 0) + { + /* PATH_MAX is bounded. */ + char *buf, *rp, *ret; + buf = (char *) malloc (path_max); + if (buf == NULL) + return NULL; + rp = realpath (filename, buf); + ret = strdup (rp ? rp : filename); + free (buf); + return ret; + } + } +#endif + + /* The MS Windows method. If we don't have realpath, we assume we + don't have symlinks and just canonicalize to a Windows absolute + path. GetFullPath converts ../ and ./ in relative paths to + absolute paths, filling in current drive if one is not given + or using the current directory of a specified drive (eg, "E:foo"). + It also converts all forward slashes to back slashes. */ +#if defined (_WIN32) + { + char buf[MAX_PATH]; + char* basename; + DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename); + if (len == 0 || len > MAX_PATH - 1) + return strdup (filename); + else + { + /* The file system is case-preserving but case-insensitive, + Canonicalize to lowercase, using the codepage associated + with the process locale. */ + CharLowerBuff (buf, len); + return strdup (buf); + } + } +#endif + + /* This system is a lost cause, just duplicate the filename. */ + return strdup (filename); +} diff --git a/jtag/src/lib/make-relative-prefix.c b/jtag/src/lib/make-relative-prefix.c new file mode 100644 index 00000000..80e7f92f --- /dev/null +++ b/jtag/src/lib/make-relative-prefix.c @@ -0,0 +1,414 @@ +/* Relative (relocatable) prefix support. + Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2006 Free Software Foundation, Inc. + +This file is part of libiberty. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA +02110-1301, USA. */ + +/* + +@deftypefn Extension {const char*} make_relative_prefix (const char *@var{progname}, const char *@var{bin_prefix}, const char *@var{prefix}) + +Given three paths @var{progname}, @var{bin_prefix}, @var{prefix}, +return the path that is in the same position relative to +@var{progname}'s directory as @var{prefix} is relative to +@var{bin_prefix}. That is, a string starting with the directory +portion of @var{progname}, followed by a relative pathname of the +difference between @var{bin_prefix} and @var{prefix}. + +If @var{progname} does not contain any directory separators, +@code{make_relative_prefix} will search @env{PATH} to find a program +named @var{progname}. Also, if @var{progname} is a symbolic link, +the symbolic link will be resolved. + +For example, if @var{bin_prefix} is @code{/alpha/beta/gamma/gcc/delta}, +@var{prefix} is @code{/alpha/beta/gamma/omega/}, and @var{progname} is +@code{/red/green/blue/gcc}, then this function will return +@code{/red/green/blue/../../omega/}. + +The return value is normally allocated via @code{malloc}. If no +relative prefix can be found, return @code{NULL}. + +@end deftypefn + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +#include "ansidecl.h" +#include "libiberty.h" + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) \ + || defined (__DJGPP__) || defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define HAVE_HOST_EXECUTABLE_SUFFIX +# define HOST_EXECUTABLE_SUFFIX ".exe" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# define PATH_SEPARATOR ';' +#else +# define PATH_SEPARATOR ':' +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif + +#define DIR_UP ".." + +static char *save_string (const char *, int); +static char **split_directories (const char *, int *); +static void free_split_directories (char **); + +static char * +save_string (const char *s, int len) +{ + char *result = (char *) malloc (len + 1); + + memcpy (result, s, len); + result[len] = 0; + return result; +} + +/* Split a filename into component directories. */ + +static char ** +split_directories (const char *name, int *ptr_num_dirs) +{ + int num_dirs = 0; + char **dirs; + const char *p, *q; + int ch; + + /* Count the number of directories. Special case MSDOS disk names as part + of the initial directory. */ + p = name; +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + if (name[1] == ':' && IS_DIR_SEPARATOR (name[2])) + { + p += 3; + num_dirs++; + } +#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ + + while ((ch = *p++) != '\0') + { + if (IS_DIR_SEPARATOR (ch)) + { + num_dirs++; + while (IS_DIR_SEPARATOR (*p)) + p++; + } + } + + dirs = (char **) malloc (sizeof (char *) * (num_dirs + 2)); + if (dirs == NULL) + return NULL; + + /* Now copy the directory parts. */ + num_dirs = 0; + p = name; +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + if (name[1] == ':' && IS_DIR_SEPARATOR (name[2])) + { + dirs[num_dirs++] = save_string (p, 3); + if (dirs[num_dirs - 1] == NULL) + { + free (dirs); + return NULL; + } + p += 3; + } +#endif /* HAVE_DOS_BASED_FILE_SYSTEM */ + + q = p; + while ((ch = *p++) != '\0') + { + if (IS_DIR_SEPARATOR (ch)) + { + while (IS_DIR_SEPARATOR (*p)) + p++; + + dirs[num_dirs++] = save_string (q, p - q); + if (dirs[num_dirs - 1] == NULL) + { + dirs[num_dirs] = NULL; + free_split_directories (dirs); + return NULL; + } + q = p; + } + } + + if (p - 1 - q > 0) + dirs[num_dirs++] = save_string (q, p - 1 - q); + dirs[num_dirs] = NULL; + + if (dirs[num_dirs - 1] == NULL) + { + free_split_directories (dirs); + return NULL; + } + + if (ptr_num_dirs) + *ptr_num_dirs = num_dirs; + return dirs; +} + +/* Release storage held by split directories. */ + +static void +free_split_directories (char **dirs) +{ + int i = 0; + + if (dirs != NULL) + { + while (dirs[i] != NULL) + free (dirs[i++]); + + free ((char *) dirs); + } +} + +/* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets + to PREFIX starting with the directory portion of PROGNAME and a relative + pathname of the difference between BIN_PREFIX and PREFIX. + + For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is + /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this + function will return /red/green/blue/../../omega/. + + If no relative prefix can be found, return NULL. */ + +static char * +make_relative_prefix_1 (const char *progname, const char *bin_prefix, + const char *prefix, const int resolve_links) +{ + char **prog_dirs = NULL, **bin_dirs = NULL, **prefix_dirs = NULL; + int prog_num, bin_num, prefix_num; + int i, n, common; + int needed_len; + char *ret = NULL, *ptr, *full_progname; + + if (progname == NULL || bin_prefix == NULL || prefix == NULL) + return NULL; + + /* If there is no full pathname, try to find the program by checking in each + of the directories specified in the PATH environment variable. */ + if (lbasename (progname) == progname) + { + char *temp; + + temp = getenv ("PATH"); + if (temp) + { + char *startp, *endp, *nstore; + size_t prefixlen = strlen (temp) + 1; + if (prefixlen < 2) + prefixlen = 2; + + nstore = (char *) alloca (prefixlen + strlen (progname) + 1); + + startp = endp = temp; + while (1) + { + if (*endp == PATH_SEPARATOR || *endp == 0) + { + if (endp == startp) + { + nstore[0] = '.'; + nstore[1] = DIR_SEPARATOR; + nstore[2] = '\0'; + } + else + { + strncpy (nstore, startp, endp - startp); + if (! IS_DIR_SEPARATOR (endp[-1])) + { + nstore[endp - startp] = DIR_SEPARATOR; + nstore[endp - startp + 1] = 0; + } + else + nstore[endp - startp] = 0; + } + strcat (nstore, progname); + if (! access (nstore, X_OK) +#ifdef HAVE_HOST_EXECUTABLE_SUFFIX + || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK) +#endif + ) + { + progname = nstore; + break; + } + + if (*endp == 0) + break; + endp = startp = endp + 1; + } + else + endp++; + } + } + } + + if ( resolve_links ) + { + full_progname = lrealpath (progname); + if (full_progname == NULL) + return NULL; + } + else + full_progname = strdup(progname); + + prog_dirs = split_directories (full_progname, &prog_num); + free (full_progname); + if (prog_dirs == NULL) + return NULL; + + bin_dirs = split_directories (bin_prefix, &bin_num); + if (bin_dirs == NULL) + goto bailout; + + /* Remove the program name from comparison of directory names. */ + prog_num--; + + /* If we are still installed in the standard location, we don't need to + specify relative directories. Also, if argv[0] still doesn't contain + any directory specifiers after the search above, then there is not much + we can do. */ + if (prog_num == bin_num) + { + for (i = 0; i < bin_num; i++) + { + if (strcmp (prog_dirs[i], bin_dirs[i]) != 0) + break; + } + + if (prog_num <= 0 || i == bin_num) + goto bailout; + } + + prefix_dirs = split_directories (prefix, &prefix_num); + if (prefix_dirs == NULL) + goto bailout; + + /* Find how many directories are in common between bin_prefix & prefix. */ + n = (prefix_num < bin_num) ? prefix_num : bin_num; + for (common = 0; common < n; common++) + { + if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0) + break; + } + + /* If there are no common directories, there can be no relative prefix. */ + if (common == 0) + goto bailout; + + /* Two passes: first figure out the size of the result string, and + then construct it. */ + needed_len = 0; + for (i = 0; i < prog_num; i++) + needed_len += strlen (prog_dirs[i]); + needed_len += sizeof (DIR_UP) * (bin_num - common); + for (i = common; i < prefix_num; i++) + needed_len += strlen (prefix_dirs[i]); + needed_len += 1; /* Trailing NUL. */ + + ret = (char *) malloc (needed_len); + if (ret == NULL) + goto bailout; + + /* Build up the pathnames in argv[0]. */ + *ret = '\0'; + for (i = 0; i < prog_num; i++) + strcat (ret, prog_dirs[i]); + + /* Now build up the ..'s. */ + ptr = ret + strlen(ret); + for (i = common; i < bin_num; i++) + { + strcpy (ptr, DIR_UP); + ptr += sizeof (DIR_UP) - 1; + *(ptr++) = DIR_SEPARATOR; + } + *ptr = '\0'; + + /* Put in directories to move over to prefix. */ + for (i = common; i < prefix_num; i++) + strcat (ret, prefix_dirs[i]); + + bailout: + free_split_directories (prog_dirs); + free_split_directories (bin_dirs); + free_split_directories (prefix_dirs); + + return ret; +} + + +/* Do the full job, including symlink resolution. + This path will find files installed in the same place as the + program even when a soft link has been made to the program + from somwhere else. */ + +char * +make_relative_prefix (const char *progname, const char *bin_prefix, + const char *prefix) +{ + return make_relative_prefix_1 (progname, bin_prefix, prefix, 1); +} + +/* Make the relative pathname without attempting to resolve any links. + '..' etc may also be left in the pathname. + This will find the files the user meant the program to find if the + installation is patched together with soft links. */ + +char * +make_relative_prefix_ignore_links (const char *progname, + const char *bin_prefix, + const char *prefix) +{ + return make_relative_prefix_1 (progname, bin_prefix, prefix, 0); +} + diff --git a/jtag/src/lib/safe-ctype.h b/jtag/src/lib/safe-ctype.h new file mode 100644 index 00000000..e59b357c --- /dev/null +++ b/jtag/src/lib/safe-ctype.h @@ -0,0 +1,119 @@ +/* replacement macros. + + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Contributed by Zack Weinberg . + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ + +/* This is a compatible replacement of the standard C library's + with the following properties: + + - Implements all isxxx() macros required by C99. + - Also implements some character classes useful when + parsing C-like languages. + - Does not change behavior depending on the current locale. + - Behaves properly for all values in the range of a signed or + unsigned char. + + To avoid conflicts, this header defines the isxxx functions in upper + case, e.g. ISALPHA not isalpha. */ + +#ifndef SAFE_CTYPE_H +#define SAFE_CTYPE_H + +#ifdef isalpha + #error "safe-ctype.h and ctype.h may not be used simultaneously" +#endif + +/* Determine host character set. */ +#define HOST_CHARSET_UNKNOWN 0 +#define HOST_CHARSET_ASCII 1 +#define HOST_CHARSET_EBCDIC 2 + +#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \ + && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21 +# define HOST_CHARSET HOST_CHARSET_ASCII +#else +# if '\n' == 0x15 && ' ' == 0x40 && '0' == 0xF0 \ + && 'A' == 0xC1 && 'a' == 0x81 && '!' == 0x5A +# define HOST_CHARSET HOST_CHARSET_EBCDIC +# else +# define HOST_CHARSET HOST_CHARSET_UNKNOWN +# endif +#endif + +/* Categories. */ + +enum { + /* In C99 */ + _sch_isblank = 0x0001, /* space \t */ + _sch_iscntrl = 0x0002, /* nonprinting characters */ + _sch_isdigit = 0x0004, /* 0-9 */ + _sch_islower = 0x0008, /* a-z */ + _sch_isprint = 0x0010, /* any printing character including ' ' */ + _sch_ispunct = 0x0020, /* all punctuation */ + _sch_isspace = 0x0040, /* space \t \n \r \f \v */ + _sch_isupper = 0x0080, /* A-Z */ + _sch_isxdigit = 0x0100, /* 0-9A-Fa-f */ + + /* Extra categories useful to cpplib. */ + _sch_isidst = 0x0200, /* A-Za-z_ */ + _sch_isvsp = 0x0400, /* \n \r */ + _sch_isnvsp = 0x0800, /* space \t \f \v \0 */ + + /* Combinations of the above. */ + _sch_isalpha = _sch_isupper|_sch_islower, /* A-Za-z */ + _sch_isalnum = _sch_isalpha|_sch_isdigit, /* A-Za-z0-9 */ + _sch_isidnum = _sch_isidst|_sch_isdigit, /* A-Za-z0-9_ */ + _sch_isgraph = _sch_isalnum|_sch_ispunct, /* isprint and not space */ + _sch_iscppsp = _sch_isvsp|_sch_isnvsp, /* isspace + \0 */ + _sch_isbasic = _sch_isprint|_sch_iscppsp /* basic charset of ISO C + (plus ` and @) */ +}; + +/* Character classification. */ +extern const unsigned short _sch_istable[256]; + +#define _sch_test(c, bit) (_sch_istable[(c) & 0xff] & (unsigned short)(bit)) + +#define ISALPHA(c) _sch_test(c, _sch_isalpha) +#define ISALNUM(c) _sch_test(c, _sch_isalnum) +#define ISBLANK(c) _sch_test(c, _sch_isblank) +#define ISCNTRL(c) _sch_test(c, _sch_iscntrl) +#define ISDIGIT(c) _sch_test(c, _sch_isdigit) +#define ISGRAPH(c) _sch_test(c, _sch_isgraph) +#define ISLOWER(c) _sch_test(c, _sch_islower) +#define ISPRINT(c) _sch_test(c, _sch_isprint) +#define ISPUNCT(c) _sch_test(c, _sch_ispunct) +#define ISSPACE(c) _sch_test(c, _sch_isspace) +#define ISUPPER(c) _sch_test(c, _sch_isupper) +#define ISXDIGIT(c) _sch_test(c, _sch_isxdigit) + +#define ISIDNUM(c) _sch_test(c, _sch_isidnum) +#define ISIDST(c) _sch_test(c, _sch_isidst) +#define IS_ISOBASIC(c) _sch_test(c, _sch_isbasic) +#define IS_VSPACE(c) _sch_test(c, _sch_isvsp) +#define IS_NVSPACE(c) _sch_test(c, _sch_isnvsp) +#define IS_SPACE_OR_NUL(c) _sch_test(c, _sch_iscppsp) + +/* Character transformation. */ +extern const unsigned char _sch_toupper[256]; +extern const unsigned char _sch_tolower[256]; +#define TOUPPER(c) _sch_toupper[(c) & 0xff] +#define TOLOWER(c) _sch_tolower[(c) & 0xff] + +#endif /* SAFE_CTYPE_H */