diff options
| author | karl <karl> | 2004-05-14 17:07:14 +0000 |
|---|---|---|
| committer | karl <karl> | 2004-05-14 17:07:14 +0000 |
| commit | 7af5fd0fe2d930e0686dc989c239479bf23d01e2 (patch) | |
| tree | ebdb74bede6f8806e79f2ce5e9a2375f8867904c /lib | |
| parent | e9f0ddc0f8b3ff1a8419acef3ddad9cc81dc1231 (diff) | |
| download | fontutils-7af5fd0fe2d930e0686dc989c239479bf23d01e2.tar.gz | |
checkpoint
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/GNUmakefile | 4 | ||||
| -rw-r--r-- | lib/atou.c | 30 | ||||
| -rw-r--r-- | lib/atou.o | bin | 4976 -> 0 bytes | |||
| -rw-r--r-- | lib/concatn.c | 70 | ||||
| -rw-r--r-- | lib/dir.c | 85 | ||||
| -rw-r--r-- | lib/extend-fname.c | 34 | ||||
| -rw-r--r-- | lib/find-suffix.c | 45 | ||||
| -rw-r--r-- | lib/hash.c | 180 | ||||
| -rw-r--r-- | lib/make-suffix.c | 50 | ||||
| -rw-r--r-- | lib/progname.c | 617 | ||||
| -rw-r--r-- | lib/rm-suffix.c | 42 | ||||
| -rw-r--r-- | lib/xcalloc.c | 35 | ||||
| -rw-r--r-- | lib/xfopen.c | 47 | ||||
| -rw-r--r-- | lib/xfseek.c | 27 | ||||
| -rw-r--r-- | lib/xfseek.o | bin | 3592 -> 0 bytes | |||
| -rw-r--r-- | lib/xftell.c | 31 | ||||
| -rw-r--r-- | lib/xftell.o | bin | 3648 -> 0 bytes | |||
| -rw-r--r-- | lib/xmalloc.c | 41 | ||||
| -rw-r--r-- | lib/xrealloc.c | 54 | ||||
| -rw-r--r-- | lib/xstrdup.c | 4 |
20 files changed, 1393 insertions, 3 deletions
diff --git a/lib/GNUmakefile b/lib/GNUmakefile index ac9a0d7..fbfe941 100644 --- a/lib/GNUmakefile +++ b/lib/GNUmakefile @@ -30,7 +30,9 @@ encoding float-ok fmod file-input file-output filename fix-num font \ hexify identity integer-ok libfile line list logreport \ make-prefix math now numtoa pathsrch rand report safe-free scaled-num \ spline statistics str-lcase str-to-bit substring varstring vector \ -xmessage xopendir xrename +xmessage xopendir xrename \ +atou concatn dir extend-fname find-suffix hash make-suffix progname rm-suffix \ +xcalloc xfopen xfseek xftell xmalloc xrealloc xstrdup include ../data/defs.make include ../data/defslib.make diff --git a/lib/atou.c b/lib/atou.c new file mode 100644 index 0000000..d2e1cda --- /dev/null +++ b/lib/atou.c @@ -0,0 +1,30 @@ +/* atou.c: like atoi, but if the number is negative, abort. + +Copyright (C) 1992, 95 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" + +unsigned +atou P1C(const_string, s) +{ + int i = atoi (s); + + if (i < 0) + FATAL1 ("I expected a positive number, not %d", i); + + return i; +} diff --git a/lib/atou.o b/lib/atou.o Binary files differdeleted file mode 100644 index d15e642..0000000 --- a/lib/atou.o +++ /dev/null diff --git a/lib/concatn.c b/lib/concatn.c new file mode 100644 index 0000000..73f7d26 --- /dev/null +++ b/lib/concatn.c @@ -0,0 +1,70 @@ +/* concatn.c: Concatenate an arbitrary number of strings. + +Copyright (C) 1993, 95 Karl Berry. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + +#include <kpathsea/concatn.h> + + +/* OK, it would be epsilon more efficient to compute the total length + and then do the copying ourselves, but I doubt it matters in reality. */ + +string +concatn PVAR1C(const_string, str1, ap) +{ + string arg; + string ret; + + if (!str1) + return NULL; + + ret = xstrdup (str1); + + while ((arg = va_arg (ap, string)) != NULL) + { + string temp = concat (ret, arg); + free (ret); + ret = temp; + } + va_end (ap); + + return ret; +}} + +#ifdef TEST +int +main () +{ + printf ("null = \"%s\"\n", concatn (NULL)); + printf ("\"a\" = \"%s\"\n", concatn ("a", NULL)); + printf ("\"ab\" = \"%s\"\n", concatn ("a", "b", NULL)); + printf ("\"abc\" = \"%s\"\n", concatn ("a", "b", "c", NULL)); + printf ("\"abcd\" = \"%s\"\n", concatn ("ab", "cd", NULL)); + printf ("\"abcde\" = \"%s\"\n", concatn ("ab", "c", "de", NULL)); + printf ("\"abcdef\" = \"%s\"\n", concatn ("", "a", "", "bcd", "ef", NULL)); + return 0; +} + +#endif /* TEST */ + + +/* +Local variables: +standalone-compile-command: "gcc -posix -g -I. -I.. -DTEST concatn.c kpathsea.a" +End: +*/ diff --git a/lib/dir.c b/lib/dir.c new file mode 100644 index 0000000..1ca64ae --- /dev/null +++ b/lib/dir.c @@ -0,0 +1,85 @@ +/* dir.c: directory operations. + +Copyright (C) 1992, 93, 94, 95, 2004 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" + +#include <kpathsea/c-dir.h> +#include <kpathsea/c-stat.h> +#include <kpathsea/hash.h> + + +/* Return true if FN is a directory or a symlink to a directory, + false if not. */ + +boolean +dir_p P1C(const_string, fn) +{ + struct stat stats; + return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode); +} + + +/* Return -1 if FN isn't a directory, else its number of links. + Duplicate the call to stat; no need to incur overhead of a function + call for that little bit of cleanliness. */ + +int +dir_links P1C(const_string, fn) +{ + static hash_table_type link_table; + string *hash_ret; + long ret; + + if (link_table.size == 0) + link_table = hash_create (457); + +#ifdef KPSE_DEBUG + /* This is annoying, but since we're storing integers as pointers, we + can't print them as strings. */ + if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) + kpse_debug_hash_lookup_int = true; +#endif + + hash_ret = hash_lookup (link_table, fn); + +#ifdef KPSE_DEBUG + if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) + kpse_debug_hash_lookup_int = false; +#endif + + /* Have to cast the int we need to/from the const_string that the hash + table stores for values. Let's hope an int fits in a pointer. */ + if (hash_ret) + ret = (long) *hash_ret; + else + { + struct stat stats; + ret = stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode) + ? stats.st_nlink : -1; + + /* It's up to us to copy the value. */ + hash_insert (&link_table, xstrdup (fn), (const_string) ret); + +#ifdef KPSE_DEBUG + if (KPSE_DEBUG_P (KPSE_DEBUG_STAT)) + DEBUGF2 ("dir_links(%s) => %ld\n", fn, ret); +#endif + } + + return ret; +} diff --git a/lib/extend-fname.c b/lib/extend-fname.c new file mode 100644 index 0000000..98d118c --- /dev/null +++ b/lib/extend-fname.c @@ -0,0 +1,34 @@ +/* extend-fname.c: give a filename a suffix, if necessary. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + + +/* We may or may not return NAME. It's up to the caller not to assume + the return value is modifiable. */ + +string +extend_filename P2C(const_string, name, const_string, default_suffix) +{ + string new_s; + const_string suffix = find_suffix (name); + + new_s = suffix == NULL ? concat3 (name, ".", default_suffix) + : (string) name; + return new_s; +} diff --git a/lib/find-suffix.c b/lib/find-suffix.c new file mode 100644 index 0000000..9774713 --- /dev/null +++ b/lib/find-suffix.c @@ -0,0 +1,45 @@ +/* find-suffix.c: return the stuff after a dot. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + +#include <kpathsea/c-pathch.h> + + +/* Return pointer to first character after `.' in last directory element + of NAME. If the name is `foo' or `/foo.bar/baz', we have no extension. */ + +string +find_suffix P1C(const_string, name) +{ + const_string slash_pos; + string dot_pos = strrchr (name, '.'); + + if (dot_pos == NULL) + return NULL; + + for (slash_pos = name + strlen (name); + slash_pos > dot_pos && !IS_DIR_SEP (*slash_pos); + slash_pos--) + ; + + return slash_pos > dot_pos ? NULL : dot_pos + 1; +} + + + diff --git a/lib/hash.c b/lib/hash.c new file mode 100644 index 0000000..f6450b6 --- /dev/null +++ b/lib/hash.c @@ -0,0 +1,180 @@ +/* hash.c: hash table operations. + +Copyright (C) 1994, 95, 96 Karl Berry. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + +#include <kpathsea/hash.h> +#include <kpathsea/str-list.h> + + +/* The hash function. We go for simplicity here. */ + +/* All our hash tables are related to filenames. */ +#ifdef MONOCASE_FILENAMES +#define TRANSFORM(x) toupper (x) +#else +#define TRANSFORM(x) (x) +#endif + +static unsigned +hash P2C(hash_table_type, table, const_string, key) +{ + unsigned n = 0; + + /* Our keys aren't often anagrams of each other, so no point in + weighting the characters. */ + while (*key != 0) + n = (n + n + TRANSFORM (*key++)) % table.size; + + return n; +} + +hash_table_type +hash_create P1C(unsigned, size) +{ + unsigned b; + hash_table_type ret; + ret.buckets = XTALLOC (size, hash_element_type *); + ret.size = size; + + /* calloc's zeroes aren't necessarily NULL, according to ANSI, so be + safe. (Not that I know of any exceptions in reality.) */ + for (b = 0; b <ret.size; b++) + ret.buckets[b] = NULL; + + return ret; +} + +/* Whether or not KEY is already in MAP, insert it and VALUE. Do not + duplicate the strings, in case they're being purposefully shared. */ + +void +hash_insert P3C(hash_table_type *, table, const_string, key, + const_string, value) +{ + unsigned n = hash (*table, key); + hash_element_type *new_elt = XTALLOC1 (hash_element_type); + + new_elt->key = key; + new_elt->value = value; + new_elt->next = NULL; + + /* Insert the new element at the end of the list. */ + if (!table->buckets[n]) + /* first element in bucket is a special case. */ + table->buckets[n] = new_elt; + else + { + hash_element_type *loc = table->buckets[n]; + while (loc->next) /* Find the last element. */ + loc = loc->next; + loc->next = new_elt; /* Insert the new one after. */ + } +} + +/* Look up STR in MAP. Return a (dynamically-allocated) list of the + corresponding strings or NULL if no match. */ + +#ifdef KPSE_DEBUG +/* Print the hash values as integers if this is nonzero. */ +boolean kpse_debug_hash_lookup_int = false; +#endif + +string * +hash_lookup P2C(hash_table_type, table, const_string, key) +{ + hash_element_type *p; + str_list_type ret; + unsigned n = hash (table, key); + ret = str_list_init (); + + /* Look at everything in this bucket. */ + for (p = table.buckets[n]; p != NULL; p = p->next) + if (FILESTRCASEEQ (key, p->key)) + /* Cast because the general str_list_type shouldn't force const data. */ + str_list_add (&ret, (string) p->value); + + /* If we found anything, mark end of list with null. */ + if (STR_LIST (ret)) + str_list_add (&ret, NULL); + +#ifdef KPSE_DEBUG + if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) + { + DEBUGF1 ("hash_lookup(%s) =>", key); + if (!STR_LIST (ret)) + fputs (" (nil)\n", stderr); + else + { + string *r; + for (r = STR_LIST (ret); *r; r++) + { + putc (' ', stderr); + if (kpse_debug_hash_lookup_int) + fprintf (stderr, "%ld", (long) *r); + else + fputs (*r, stderr); + } + putc ('\n', stderr); + } + fflush (stderr); + } +#endif + + return STR_LIST (ret); +} + +/* We only print nonempty buckets, to decrease output volume. */ + +void +hash_print P2C(hash_table_type, table, boolean, summary_only) +{ + unsigned b; + unsigned total_elements = 0, total_buckets = 0; + + for (b = 0; b < table.size; b++) { + hash_element_type *bucket = table.buckets[b]; + + if (bucket) { + unsigned len = 1; + hash_element_type *tb; + + total_buckets++; + if (!summary_only) fprintf (stderr, "%4d ", b); + + for (tb = bucket->next; tb != NULL; tb = tb->next) + len++; + if (!summary_only) fprintf (stderr, ":%-5d", len); + total_elements += len; + + if (!summary_only) { + for (tb = bucket; tb != NULL; tb = tb->next) + fprintf (stderr, " %s=>%s", tb->key, tb->value); + putc ('\n', stderr); + } + } + } + + fprintf (stderr, + "%u buckets, %u nonempty (%u%%); %u entries, average chain %.1f.\n", + table.size, + total_buckets, + 100 * total_buckets / table.size, + total_elements, + total_buckets ? total_elements / (double) total_buckets : 0.0); +} diff --git a/lib/make-suffix.c b/lib/make-suffix.c new file mode 100644 index 0000000..1935c3f --- /dev/null +++ b/lib/make-suffix.c @@ -0,0 +1,50 @@ +/* make-suffix.c: unconditionally add a filename suffix. + +Copyright (C) 1992, 93, 95 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> +#include <kpathsea/c-pathch.h> + +/* Return a new string: S suffixed with SUFFIX, regardless of what it + was before. This returns a newly allocated string. */ + +string +make_suffix P2C(const_string, s, const_string, suffix) +{ + string new_s; + const_string dot_pos = strrchr (s, '.'); + const_string slash_pos; + + for (slash_pos = s + strlen (s) - 1; slash_pos > dot_pos && slash_pos > s; + slash_pos--) { + if (IS_DIR_SEP (*slash_pos)) + break; + } + + if (dot_pos == NULL || slash_pos > dot_pos ) + new_s = concat3 (s, ".", suffix); + else + { + unsigned past_dot_index = dot_pos + 1 - s; + + new_s = xmalloc (past_dot_index + strlen (suffix) + 1); + strncpy (new_s, s, dot_pos + 1 - s); + strcpy (new_s + past_dot_index, suffix); + } + + return new_s; +} diff --git a/lib/progname.c b/lib/progname.c new file mode 100644 index 0000000..d269e2f --- /dev/null +++ b/lib/progname.c @@ -0,0 +1,617 @@ +/* progname.c: the executable name we were invoked as; general initialization. + +Copyright (C) 1994, 96, 97 Karl Berry. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> +#include <kpathsea/absolute.h> +#include <kpathsea/c-pathch.h> +#include <kpathsea/c-stat.h> +#include <kpathsea/pathsearch.h> +/* For kpse_reset_progname */ +#include <kpathsea/tex-file.h> + +#ifdef WIN32 +#include <kpathsea/c-pathmx.h> +#endif + +/* NeXT does not define the standard macros, but has the equivalent. + WIN32 doesn't define them either, and doesn't have them. + From: Gregor Hoffleit <flight@mathi.uni-heidelberg.de>. */ +#ifndef S_IXUSR +#ifdef WIN32 +#define S_IXUSR 0 +#define S_IXGRP 0 +#define S_IXOTH 0 +#else /* not WIN32 */ +#define S_IXUSR 0100 +#endif /* not WIN32 */ +#endif /* not S_IXUSR */ +#ifndef S_IXGRP +#define S_IXGRP 0010 +#endif +#ifndef S_IXOTH +#define S_IXOTH 0001 +#endif + +#ifndef HAVE_PROGRAM_INVOCATION_NAME +/* Don't redefine the variables if glibc already has. */ +string program_invocation_name = NULL; +string program_invocation_short_name = NULL; +#endif +/* And the variable for the program we pretend to be. */ +string kpse_program_name = NULL; + +/* Return directory for NAME. This is "." if NAME contains no directory + separators (should never happen for selfdir), else whatever precedes + the final directory separator, but with multiple separators stripped. + For example, `my_dirname ("/foo//bar.baz")' returns "/foo". Always + return a new string. */ + +static string +my_dirname P1C(const_string, name) +{ + string ret; + unsigned loc = strlen (name); + + for (loc = strlen (name); loc > 0 && !IS_DIR_SEP (name[loc-1]); loc--) + ; + + if (loc) { + /* If have ///a, must return /, so don't strip off everything. */ + unsigned limit = NAME_BEGINS_WITH_DEVICE (name) ? 3 : 1; + while (loc > limit && IS_DIR_SEP (name[loc-1]) + && !IS_DEVICE_SEP (name[loc-1])) { + loc--; + } + ret = xmalloc (loc + 1); + strncpy (ret, name, loc); + ret[loc] = 0; + } else { + /* No directory separators at all, so return the current directory. + The way this is used in kpathsea, this should never happen. */ + ret = xstrdup ("."); + } + + return ret; +} + +#ifndef WIN32 +/* From a standalone program `ll' to expand symlinks written by Kimbo Mundy. + Don't bother to compile if we don't have symlinks; thus we can assume + / as the separator. Also don't try to use basename, etc., or + handle arbitrary filename length. Mixed case function names because + that's what kimbo liked. */ + +#ifdef S_ISLNK +static int ll_verbose = 0; +static int ll_loop = 0; + +#undef BSIZE +#define BSIZE 2048 /* sorry */ + + +/* Read link FN into SYM. */ + +static void +ReadSymLink (fn, sym) + char *fn, *sym; +{ + register int n = readlink (fn, sym, BSIZE); + if (n < 0) { + perror (fn); + exit (1); + } + sym[n] = 0; +} + + +/* Strip first component from S, and also return it in a static buffer. */ + +static char * +StripFirst (s) + register char *s; +{ + static char buf[BSIZE]; + register char *s1; + + /* Find the end of the first path element */ + for (s1 = s; *s1 && (*s1 != '/' || s1 == s); s1++) + ; + + /* Copy it into buf and null-terminate it. */ + strncpy (buf, s, s1 - s); + buf[s1 - s] = 0; + + /* Skip over the leading / (if any) */ + if (*s1 == '/') + ++s1; + + /* Squeeze out the element */ + while ((*s++ = *s1++) != 0) + ; + + return buf; +} + + +/* Strip last component from S, and also return it in a static buffer. */ + +static char * +StripLast (s) + register char *s; +{ + static char buf[BSIZE]; + register char *s1; + + for (s1 = s + strlen (s); s1 > s && *s1 != '/'; s1--) + ; + strcpy (buf, s1 + (*s1 == '/')); + *s1 = 0; + + return buf; +} + + +/* Copy first path element from B to A, removing it from B. */ + +static void +CopyFirst (a, b) + register char *a; + char *b; +{ + register int length = strlen (a); + + if (length > 0 && a[length - 1] != '/') { + a[length] = '/'; + a[length + 1] = 0; + } + strcat (a, StripFirst (b)); +} + +/* Returns NULL on error. Prints intermediate results if global + `ll_verbose' is nonzero. */ + +#define EX(s) (strlen (s) && strcmp (s, "/") ? "/" : "") +#define EXPOS EX(post) +#define EXPRE EX(pre) + +static char * +expand_symlinks (s) + char *s; +{ + static char pre[BSIZE]; /* return value */ + char post[BSIZE], sym[BSIZE], tmp[BSIZE], before[BSIZE]; + char *cp; + char a; + struct stat st; + int done; + + /* Check for symlink loops. It's difficult to check for all the + possibilities ourselves, so let the kernel do it. And make it + conditional so that people can see where the infinite loop is + being caused (see engtools#1536). */ + if (!ll_loop) { + FILE *f = fopen (s, "r"); + if (!f && errno == ELOOP) { + /* Not worried about other errors, we'll get to them in due course. */ + perror (s); + return NULL; + } + if (f) fclose (f); + } + + strcpy (post, s); + strcpy (pre, ""); + + while (strlen (post) != 0) { + CopyFirst (pre, post); + + if (lstat (pre, &st) != 0) { + fprintf (stderr, "lstat(%s) failed ...\n", pre); + perror (pre); + return NULL; + } + + if (S_ISLNK (st.st_mode)) { + ReadSymLink (pre, sym); + + if (!strncmp (sym, "/", 1)) { + if (ll_verbose) + printf ("[%s]%s%s -> [%s]%s%s\n", pre, EXPOS, post, sym, EXPOS,post); + strcpy (pre, ""); + + } else { + a = pre[0]; /* handle links through the root */ + strcpy (tmp, StripLast (pre)); + if (!strlen (pre) && a == '/') + strcpy (pre, "/"); + + if (ll_verbose) { + sprintf (before, "%s%s[%s]%s%s", pre, EXPRE, tmp, EXPOS, post); + printf ("%s -> %s%s[%s]%s%s\n", before, pre, EXPRE, sym, EXPOS,post); + } + + /* Strip "../" path elements from the front of sym; print + new result if there were any such elements. */ + done = 0; + a = pre[0]; /* handle links through the root */ + while (!strncmp (sym, "..", 2) + && (sym[2] == 0 || sym[2] == '/') + && strlen (pre) != 0 + && strcmp (pre, ".") + && strcmp (pre, "..") + && (strlen (pre) < 3 + || strcmp (pre + strlen (pre) - 3, "/.."))) { + done = 1; + StripFirst (sym); + StripLast (pre); + } + + if (done && ll_verbose) { + for (cp = before; *cp;) + *cp++ = ' '; + if (strlen (sym)) + printf ("%s == %s%s%s%s%s\n", before, pre, EXPRE, sym, EXPOS,post); + else + printf ("%s == %s%s%s\n", before, pre, EXPOS, post); + } + if (!strlen (pre) && a == '/') + strcpy (pre, "/"); + } + + if (strlen (post) != 0 && strlen (sym) != 0) + strcat (sym, "/"); + + strcat (sym, post); + strcpy (post, sym); + } + } + + return pre; +} +#else /* not S_ISLNK */ +#define expand_symlinks(s) (s) +#endif /* not S_ISLNK */ + +/* Remove .'s and ..'s in DIR, to avoid problems with relative symlinks + as the program name, etc. This does not canonicalize symlinks. */ + +static string +remove_dots P1C(string, dir) +{ +#ifdef AMIGA + return dir; +#else + string c; + unsigned len; + string ret = (string) ""; /* We always reassign. */ + + for (c = kpse_filename_component (dir); c; + c = kpse_filename_component (NULL)) { + if (STREQ (c, ".")) { + /* If leading ., replace with cwd. Else ignore. */ + if (*ret == 0) { + ret = xgetcwd (); + } + + } else if (STREQ (c, "..")) { + /* If leading .., start with my_dirname (cwd). Else remove last + component from ret, if any. */ + if (*ret == 0) { + string dot = xgetcwd (); + ret = my_dirname (dot); + free (dot); + } else { + unsigned last; + for (last = strlen (ret); + last > (NAME_BEGINS_WITH_DEVICE (ret) ? 2 : 0); + last--) { + if (IS_DIR_SEP (ret[last - 1])) { + /* If we have `/../', that's the same as `/'. */ + if (last > 1) { + ret[last] = 0; + } + break; + } + } + } + + } else { + /* Not . or ..; just append. Include a directory separator unless + our string already ends with one. This also changes all directory + separators into the canonical DIR_SEP_STRING. */ + string temp; + len = strlen (ret); + temp = concat3 (ret, ((len > 0 && ret[len - 1] == DIR_SEP) + || (NAME_BEGINS_WITH_DEVICE (c) && *ret == 0)) + ? "" : DIR_SEP_STRING, + c); + if (*ret) + free (ret); + ret = temp; + } + } + + /* Remove a trailing /, just in case it snuck in. */ + len = strlen (ret); + if (len > 0 && ret[len - 1] == DIR_SEP) { + ret[len - 1] = 0; + } + + return ret; +#endif /* not AMIGA */ +} + +/* Return directory ARGV0 comes from. Check PATH if ARGV0 is not + absolute. */ + +static string +selfdir P1C(const_string, argv0) +{ + string ret = NULL; + string self = NULL; + + if (kpse_absolute_p (argv0, true)) { + self = xstrdup (argv0); + } else { +#ifdef AMIGA +#include <dos.h> +#include <proto/dos.h> +#include <proto/exec.h> + BPTR lock; + struct DosLibrary *DOSBase + = (struct DosLibrary *) OpenLibrary ("dos.library", 0L); + assert (DOSBase); + + self = xmalloc (BUFSIZ); + lock = findpath (argv0); + if (lock != ((BPTR) -1)) { + if (getpath (lock, self) == -1) { + *self = '\0'; + } else { + strcat (self,DIR_SEP_STRING); + strcat (self,argv0); + } + UnLock (lock); + } + CloseLibrary((struct Library *) DOSBase); +#else /* not AMIGA */ + string elt; + struct stat s; + + /* Have to check PATH. But don't call kpse_path_search since we don't + want to search any ls-R's or do anything special with //'s. */ + for (elt = kpse_path_element (getenv ("PATH")); !self && elt; + elt = kpse_path_element (NULL)) { + string name = concat3 (elt, DIR_SEP_STRING, argv0); + + /* In order to do this perfectly, we'd have to check the owner bits only + if we are the file owner, and the group bits only if we belong + to the file group. That's a lot of work, though, and it's not + likely that kpathsea will ever be used with a program that's + only executable by some classes and not others. See the + `file_status' function in execute_cmd.c in bash for what's + necessary if we were to do it right. */ + if (stat (name, &s) == 0 && s.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) { + /* Do not stop at directories. */ + if (!S_ISDIR(s.st_mode)) + self = name; + } + } +#endif /* not AMIGA */ + } + + /* If argv0 is somehow dir/exename, `self' will still be NULL. */ + if (!self) + self = concat3 (".", DIR_SEP_STRING, argv0); + + ret = my_dirname (remove_dots (expand_symlinks (self))); + + free (self); + + return ret; +} +#endif /* not WIN32 */ + +void +kpse_set_program_name P2C(const_string, argv0, const_string, progname) +{ + string ext, sdir, sdir_parent, sdir_grandparent; + string s = getenv ("KPATHSEA_DEBUG"); +#ifdef WIN32 + string debug_output = getenv("KPATHSEA_DEBUG_OUTPUT"); + int err, olderr; +#endif + + /* Set debugging stuff first, in case we end up doing debuggable stuff + during this initialization. */ + if (s) { + kpathsea_debug |= atoi (s); + } + +#ifndef HAVE_PROGRAM_INVOCATION_NAME +#if defined(WIN32) + /* redirect stderr to debug_output. Easier to send logfiles. */ + if (debug_output) { + if ((err = _open(debug_output, _O_CREAT | _O_TRUNC | _O_RDWR, + _S_IREAD | _S_IWRITE)) == -1) { + WARNING1("Can't open %s for stderr redirection!\n", debug_output); + perror(debug_output); + } else if ((olderr = _dup(fileno(stderr))) == -1) { + WARNING("Can't dup() stderr!\n"); + close(err); + } else if (_dup2(err, fileno(stderr)) == -1) { + WARNING1("Can't redirect stderr to %s!\n", debug_output); + close(olderr); + close(err); + } else { + close(err); + } + } + /* Win95 always gives the short filename for argv0, not the long one. + There is only this way to catch it. It makes all the selfdir stuff + useless for win32. */ + { + char path[PATH_MAX], *fp; + HANDLE hnd; + WIN32_FIND_DATA ffd; + + /* SearchPath() always gives back an absolute directory */ + if (SearchPath(NULL, argv0, ".exe", PATH_MAX, path, &fp) == 0) + FATAL1("Can't determine where the executable %s is.\n", argv0); + if ((hnd = FindFirstFile(path, &ffd)) == NULL) + FATAL1("The following path points to an invalid file : %s\n", path); + /* slashify the dirname */ + for (fp = path; fp && *fp; fp++) + if (IS_DIR_SEP(*fp)) *fp = DIR_SEP; + /* sdir will be the directory where the executable resides, ie: c:/TeX/bin */ + sdir = my_dirname(path); + program_invocation_name = xstrdup(ffd.cFileName); + } + +#elif defined(__DJGPP__) + + /* DJGPP programs support long filenames on Windows 95, but ARGV0 there + is always made with the short 8+3 aliases of all the pathname elements. + If long names are supported, we need to convert that to a long name. + + All we really need is to call `_truename', but most of the code + below is required to deal with the special case of networked drives. */ + if (pathconf (argv0, _PC_NAME_MAX) > 12) { + char long_progname[PATH_MAX]; + + if (_truename (argv0, long_progname)) { + char *fp; + + if (long_progname[1] != ':') { + /* A complication: `_truename' returns network-specific string at + the beginning of `long_progname' when the program resides on a + networked drive, and DOS calls cannot grok such pathnames. We + need to convert the filesystem name back to a drive letter. */ + char rootname[PATH_MAX], rootdir[4]; + + if (argv0[0] && argv0[1] == ':') + rootdir[0] = argv0[0]; /* explicit drive in `argv0' */ + else + rootdir[0] = getdisk () + 'A'; + rootdir[1] = ':'; + rootdir[2] = '\\'; + rootdir[3] = '\0'; + if (_truename (rootdir, rootname)) { + /* Find out where `rootname' ends in `long_progname' and replace + it with the drive letter. */ + int root_len = strlen (rootname); + + if (IS_DIR_SEP (rootname[root_len - 1])) + root_len--; /* keep the trailing slash */ + long_progname[0] = rootdir[0]; + long_progname[1] = ':'; + memmove (long_progname + 2, long_progname + root_len, + strlen (long_progname + root_len) + 1); + } + } + + /* Convert everything to canonical form. */ + if (long_progname[0] >= 'A' && long_progname[0] <= 'Z') + long_progname[0] += 'a' - 'A'; /* make drive lower case, for beauty */ + for (fp = long_progname; *fp; fp++) + if (IS_DIR_SEP (*fp)) + *fp = DIR_SEP; + + program_invocation_name = xstrdup (long_progname); + } + else + /* If `_truename' failed, God help them, because we won't... */ + program_invocation_name = xstrdup (argv0); + } + else + program_invocation_name = xstrdup (argv0); + +#else /* !WIN32 && !__DJGPP__ */ + + program_invocation_name = xstrdup (argv0); + +#endif +#endif /* not HAVE_PROGRAM_INVOCATION_NAME */ + + /* We need to find SELFAUTOLOC *before* removing the ".exe" suffix from + the program_name, otherwise the PATH search inside selfdir will fail, + since `prog' doesn't exists as a file, there's `prog.exe' instead. */ +#ifndef WIN32 + sdir = selfdir (program_invocation_name); +#endif + /* SELFAUTODIR is actually the parent of the invocation directory, + and SELFAUTOPARENT the grandparent. This is how teTeX did it. */ + xputenv ("SELFAUTOLOC", sdir); + sdir_parent = my_dirname (sdir); + xputenv ("SELFAUTODIR", sdir_parent); + sdir_grandparent = my_dirname (sdir_parent); + xputenv ("SELFAUTOPARENT", sdir_grandparent); + + free (sdir); + free (sdir_parent); + free (sdir_grandparent); + +#ifndef PROGRAM_INVOCATION_NAME + program_invocation_short_name = (string)basename (program_invocation_name); +#endif + + if (progname) { + kpse_program_name = xstrdup (progname); + } else { + /* If configured --enable-shared and running from the build directory + with the wrapper scripts (e.g., for make check), the binaries will + be named foo.exe instead of foo. Or possibly if we're running on a + DOSISH system. */ + ext = find_suffix (program_invocation_short_name); + if (ext && FILESTRCASEEQ (ext, "exe")) { + kpse_program_name = remove_suffix (program_invocation_short_name); + } else { + kpse_program_name = xstrdup (program_invocation_short_name); + } + } +} + +/* This function is deprecated, because when we pretend to have a different + name it will look for _that_ name in the PATH if program_invocation_name + is not defined. */ +void +kpse_set_progname P1C(const_string, argv0) +{ + kpse_set_program_name (argv0, NULL); +} + +#ifdef TEST +void +main (int argc, char **argv) +{ + puts (remove_dots ("/w/kpathsea")); + puts (remove_dots ("/w//kpathsea")); + puts (remove_dots ("/w/./kpathsea")); + puts (remove_dots (".")); + puts (remove_dots ("./")); + puts (remove_dots ("./.")); + puts (remove_dots ("../kpathsea")); + puts (remove_dots ("/../w/kpathsea")); + puts (remove_dots ("/../w/kpathsea/.")); +} +/* +Local variables: +standalone-compile-command: "gcc -g -I. -I.. -DTEST progname.c STATIC/libkpathsea.a" +End: +*/ +#endif /* TEST */ diff --git a/lib/rm-suffix.c b/lib/rm-suffix.c new file mode 100644 index 0000000..192fe10 --- /dev/null +++ b/lib/rm-suffix.c @@ -0,0 +1,42 @@ +/* rm-suffix.c: remove any suffix. + +Copyright (C) 1992, 93, 95 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + + +/* Generic const warning -- see extend-fname.c. */ + +string +remove_suffix P1C(const_string, s) +{ + string ret; + const_string suffix = find_suffix (s); + + if (suffix) + { + /* Back up to before the dot. */ + suffix--; + ret = (string) xmalloc (suffix - s + 1); + strncpy (ret, s, suffix - s); + ret[suffix - s] = 0; + } + else + ret = (string) s; + + return ret; +} diff --git a/lib/xcalloc.c b/lib/xcalloc.c new file mode 100644 index 0000000..0d2d52b --- /dev/null +++ b/lib/xcalloc.c @@ -0,0 +1,35 @@ +/* xcalloc.c: calloc with error checking. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + + +address +xcalloc P2C(unsigned, nelem, unsigned, elsize) +{ + address new_mem = (address) calloc (nelem, elsize); + + if (new_mem == NULL) + { + fprintf (stderr, "xcalloc: request for %u elements of size %u failed.\n", + nelem, elsize); + abort (); + } + + return new_mem; +} diff --git a/lib/xfopen.c b/lib/xfopen.c new file mode 100644 index 0000000..084e128 --- /dev/null +++ b/lib/xfopen.c @@ -0,0 +1,47 @@ +/* xfopen.c: fopen and fclose with error checking. + +Copyright (C) 1992, 93, 95 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + + +/* These routines just check the return status from standard library + routines and abort if an error happens. */ + +FILE * +xfopen P2C(const_string, filename, const_string, mode) +{ + FILE *f; + + assert (filename && mode); + + f = fopen (filename, mode); + if (f == NULL) + FATAL_PERROR (filename); + + return f; +} + + +void +xfclose P2C(FILE *, f, const_string, filename) +{ + assert (f); + + if (fclose (f) == EOF) + FATAL_PERROR (filename); +} diff --git a/lib/xfseek.c b/lib/xfseek.c new file mode 100644 index 0000000..b104383 --- /dev/null +++ b/lib/xfseek.c @@ -0,0 +1,27 @@ +/* xfseek.c: fseek with error checking. + +Copyright (C) 1992, 95 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + + +void +xfseek P4C(FILE *, f, long, offset, int, wherefrom, string, filename) +{ + if (fseek (f, offset, wherefrom) < 0) + FATAL_PERROR (filename); +} diff --git a/lib/xfseek.o b/lib/xfseek.o Binary files differdeleted file mode 100644 index fc2e725..0000000 --- a/lib/xfseek.o +++ /dev/null diff --git a/lib/xftell.c b/lib/xftell.c new file mode 100644 index 0000000..5b421c6 --- /dev/null +++ b/lib/xftell.c @@ -0,0 +1,31 @@ +/* xftell.c: ftell with error checking. + +Copyright (C) 1992, 93, 95 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <kpathsea/config.h> + + +unsigned long +xftell P2C(FILE *, f, string, filename) +{ + long where = ftell (f); + + if (where < 0) + FATAL_PERROR (filename); + + return where; +} diff --git a/lib/xftell.o b/lib/xftell.o Binary files differdeleted file mode 100644 index 0dfe6f8..0000000 --- a/lib/xftell.o +++ /dev/null diff --git a/lib/xmalloc.c b/lib/xmalloc.c new file mode 100644 index 0000000..0371d43 --- /dev/null +++ b/lib/xmalloc.c @@ -0,0 +1,41 @@ +/* xmalloc.c: malloc with error checking. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Don't include config.h or all our other usual includes, since + it's useful to just throw this file into other programs. */ + +#include <stdio.h> +extern char *malloc (); + + +void * +xmalloc (size) + unsigned size; +{ + void *new_mem = (void *) malloc (size); + + if (new_mem == NULL) + { + fprintf (stderr, "fatal: memory exhausted (xmalloc of %u bytes).\n", + size); + /* 1 means success on VMS, so pick a random number (ASCII `K'). */ + exit (75); + } + + return new_mem; +} diff --git a/lib/xrealloc.c b/lib/xrealloc.c new file mode 100644 index 0000000..c479b98 --- /dev/null +++ b/lib/xrealloc.c @@ -0,0 +1,54 @@ +/* xrealloc.c: realloc with error checking. + +Copyright (C) 1992, 93 Free Software Foundation, Inc. + +This library 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. + +This library 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 this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Don't include config.h or all our other usual includes, since + it's useful to just throw this file into other programs. */ + +#include <stdio.h> +extern char *realloc (); + + +extern void *xmalloc (); + +void * +xrealloc (old_ptr, size) + void *old_ptr; + unsigned size; +{ + void *new_mem; + + if (old_ptr == NULL) + new_mem = xmalloc (size); + else + { + new_mem = (void *) realloc (old_ptr, size); + if (new_mem == NULL) + { + /* We used to print OLD_PTR here using %x, and casting its + value to unsigned, but that lost on the Alpha, where + pointers and unsigned had different sizes. Since the info + is of little or no value anyway, just don't print it. */ + fprintf (stderr, "fatal: memory exhausted (realloc of %u bytes).\n", + size); + /* 1 means success on VMS, so pick a random number (ASCII `B'). */ + exit (66); + } + } + + return new_mem; +} diff --git a/lib/xstrdup.c b/lib/xstrdup.c index 3ce69e9..f0ca8db 100644 --- a/lib/xstrdup.c +++ b/lib/xstrdup.c @@ -1,6 +1,6 @@ /* xstrdup.c: strdup with error checking. -Copyright (C) 1992 Free Software Foundation, Inc. +Copyright (C) 1992, 2004 Free Software Foundation, Inc. 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 @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Return a copy of S in new storage. */ string -xstrdup P1C(string, s) +xstrdup P1C(const_string, s) { string new_string = (string) xmalloc (strlen (s) + 1); return strcpy (new_string, s); |
