[ 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
master
Kolja Waschk 17 years ago
parent b067b0d946
commit d2c80944d1

@ -1,8 +1,15 @@
2008-04-03 Kolja Waschk <kawk>
* 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 <arniml@users.sourceforge.net>

@ -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

@ -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 );

@ -42,5 +42,3 @@ MAINTAINERCLEANFILES = \
bsdl_bison.c \
bsdl_bison.h \
bsdl_flex.c
INCLUDES = -DJTAG_DATA_DIR=\"$(pkgdatadir)\"

@ -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) +

@ -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)\"

@ -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) {

@ -0,0 +1,39 @@
/*
* $Id:$
*
* Licensed under the GPL-2 or later.
*/
#include <config.h>
#include "jtag.h"
#ifdef JTAG_RELOCATABLE
#include <stdlib.h>
#include <string.h>
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

@ -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++) {

@ -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)

@ -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 */

@ -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;
}

@ -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 <limits.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#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 <windows.h> /* 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);
}

@ -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 <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#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);
}

@ -0,0 +1,119 @@
/* <ctype.h> replacement macros.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Contributed by Zack Weinberg <zackw@stanford.edu>.
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 <ctype.h>
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 */
Loading…
Cancel
Save