Mercurial > hg > octave-terminal
changeset 4392:dd108fa566fa
[project @ 2003-04-26 17:00:24 by jwe]
author | jwe |
---|---|
date | Sat, 26 Apr 2003 17:00:24 +0000 |
parents | 17530e977bec |
children | f92093e0ff78 |
files | liboctave/ChangeLog liboctave/kpse.cc liboctave/kpse.h liboctave/pathsearch.cc liboctave/str-vec.cc liboctave/str-vec.h |
diffstat | 6 files changed, 354 insertions(+), 467 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,8 @@ +2003-04-26 John W. Eaton <jwe@bevo.che.wisc.edu> + + * str-vec.cc (string_vector::append (const std::string&), + string_vector::append (const string_vector&)): New methods. + 2003-04-24 John W. Eaton <jwe@bevo.che.wisc.edu> * kpse.cc, kpse.h: Replace fn_type with std::string.
--- a/liboctave/kpse.cc +++ b/liboctave/kpse.cc @@ -52,10 +52,6 @@ #include <unistd.h> #endif -#ifdef WIN32 -#include <malloc.h> -#endif /* not WIN32 */ - #include "sysdir.h" #include "statdefs.h" @@ -119,9 +115,6 @@ /* OK, we'll have tracing support. */ #define KPSE_DEBUG -/* Set a bit. */ -#define KPSE_DEBUG_SET(bit) kpathsea_debug |= 1 << (bit) - /* Test if a bit is on. */ #define KPSE_DEBUG_P(bit) (kpathsea_debug & (1 << (bit))) @@ -175,16 +168,6 @@ #define MAXPATHLEN _MAX_PATH #endif -#define HAVE_DUP2 1 -#define HAVE_RENAME 1 -#define HAVE_RMDIR 1 -#define HAVE_MKDIR 1 -#define HAVE_GETHOSTNAME 1 -#define HAVE_RANDOM 1 -#define USE_UTIME 1 -#define HAVE_MOUSE 1 -#define HAVE_TZNAME 1 - /* These have to be defined because our compilers treat __STDC__ as being defined (most of them anyway). */ @@ -204,9 +187,6 @@ #include <windows.h> -/* Defines size_t and alloca (). */ -#include <malloc.h> - /* For proper declaration of environ. */ #include <io.h> #include <fcntl.h> @@ -216,26 +196,6 @@ #endif /* WIN32 */ -/* hash.h: declarations for a hash table. */ - -/* A single (key,value) pair. */ -struct hash_element_type -{ - std::string key; - std::string value; - struct hash_element_type *next; -}; - -/* The usual arrangement of buckets initialized to null. */ -struct hash_table_type -{ - hash_element_type **buckets; - unsigned size; -}; - -static hash_table_type hash_create (unsigned size); - - /* lib.h: other stuff. */ /* Define common sorts of messages. */ @@ -266,7 +226,6 @@ #define FATAL6(str, e1, e2, e3, e4, e5, e6) \ START_FATAL (); fprintf (stderr, str, e1, e2, e3, e4, e5, e6); END_FATAL () - #define START_WARNING() do { fputs ("warning: ", stderr) #define END_WARNING() fputs (".\n", stderr); fflush (stderr); } while (0) @@ -281,7 +240,6 @@ #define WARNING4(str, e1, e2, e3, e4) \ START_WARNING (); fprintf (stderr, str, e1, e2, e3, e4); END_WARNING () - /* I find this easier to read. */ #define STREQ(s1, s2) (strcmp (s1, s2) == 0) #define STRNEQ(s1, s2, n) (strncmp (s1, s2, n) == 0) @@ -298,8 +256,6 @@ #define FILECHARCASEEQ(c1, c2) ((c1) == (c2)) #endif - - /* (Re)Allocate N items of type T using xmalloc/xrealloc. */ #define XTALLOC(n, t) ((t *) xmalloc ((n) * sizeof (t))) #define XTALLOC1(t) XTALLOC (1, t) @@ -307,40 +263,14 @@ extern "C" char *xbasename (const char *name); -static FILE *xfopen (const char *filename, const char *mode); - -static void xfclose (FILE *f, const char *filename); - #ifndef WIN32 static void xclosedir (DIR *d); #endif -static void *xmalloc (unsigned size); - -static void *xrealloc (void *old_ptr, unsigned size); - #ifndef WIN32 int dir_links (const char *fn); #endif -static unsigned hash (hash_table_type table, const std::string& key); - -static void hash_insert (hash_table_type *table, const std::string& key, - const std::string& value); - -static string_vector hash_lookup (hash_table_type table, - const std::string& key); - -static void hash_print (hash_table_type table, int summary_only); - -static char *concat (const char *s1, const char *s2); - -static char *concat3 (const char *s1, const char *s2, const char *s3); - -static void str_list_add (string_vector& l, const std::string& s); - -static void str_list_concat (string_vector& target, const string_vector& more); - static void str_llist_add (str_llist_type *l, const std::string& str); static void str_llist_float (str_llist_type *l, str_llist_elt_type *mover); @@ -349,6 +279,52 @@ #include <ctime> /* for `time' */ +/* xmalloc.c: malloc with error checking. */ + +static void * +xmalloc (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; +} + +/* xrealloc.c: realloc with error checking. */ + +static void * +xrealloc (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; +} + /* Return a copy of S in new storage. */ static char * @@ -358,6 +334,231 @@ return strcpy (new_string, s); } +/* These routines just check the return status from standard library + routines and abort if an error happens. */ + +static FILE * +xfopen (const char *filename, const char *mode) +{ + FILE *f; + + assert (filename && mode); + + f = fopen (filename, mode); + if (f == NULL) + FATAL_PERROR (filename); + + return f; +} + +static void +xfclose (FILE *f, const char *filename) +{ + assert (f); + + if (fclose (f) == EOF) + FATAL_PERROR (filename); +} + +/* Return the concatenation of S1 and S2. See `concatn.c' for a + `concatn', which takes a variable number of arguments. */ + +static char * +concat (const char *s1, const char *s2) +{ + char *answer = (char *) xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (answer, s1); + strcat (answer, s2); + + return answer; +} + +/* concat3.c: concatenate three strings. */ + +static char * +concat3 (const char *s1, const char *s2, const char *s3) +{ + char *answer + = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); + strcpy (answer, s1); + strcat (answer, s2); + strcat (answer, s3); + + return answer; +} + +/* A single (key,value) pair. */ + +struct hash_element_type +{ + std::string key; + std::string value; + struct hash_element_type *next; +}; + +/* The usual arrangement of buckets initialized to null. */ + +struct hash_table_type +{ + hash_element_type **buckets; + unsigned size; +}; + +/* 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 (hash_table_type table, const std::string& key) +{ + unsigned n = 0; + + /* Our keys aren't often anagrams of each other, so no point in + weighting the characters. */ + size_t len = key.length (); + for (size_t i = 0; i < len; i++) + n = (n + n + TRANSFORM (key[i])) % table.size; + + return n; +} + +static hash_table_type +hash_create (unsigned size) +{ + /* hash_table_type ret; changed into "static ..." to work around gcc + optimizer bug for Alpha. */ + static hash_table_type ret; + unsigned b; + ret.buckets = new hash_element_type * [size]; + ret.size = size; + + /* calloc's zeroes aren't necessarily NULL, so be safe. */ + 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. */ + +static void +hash_insert (hash_table_type *table, const std::string& key, + const std::string& value) +{ + unsigned n = hash (*table, key); + hash_element_type *new_elt = new 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. */ + +static string_vector +hash_lookup (hash_table_type table, const std::string& key) +{ + hash_element_type *p; + string_vector ret; + unsigned n = hash (table, key); + + /* Look at everything in this bucket. */ + for (p = table.buckets[n]; p != NULL; p = p->next) + if (FILESTRCASEEQ (key.c_str (), p->key.c_str ())) + /* Cast because the general string_vector shouldn't force const data. */ + ret.append (p->value); + +#ifdef KPSE_DEBUG + if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) + { + DEBUGF1 ("hash_lookup (%s) =>", key.c_str ()); + if (ret.empty ()) + fputs (" (nil)\n", stderr); + else + { + int len = ret.length (); + for (int i = 0; i < len; i++) + { + putc (' ', stderr); + fputs (ret[i].c_str (), stderr); + } + putc ('\n', stderr); + } + fflush (stderr); + } +#endif + + return ret; +} + +/* We only print nonempty buckets, to decrease output volume. */ + +static void +hash_print (hash_table_type table, int 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.c_str (), + tb->value.c_str ()); + + 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); +} + /* Here's the simple one, when a program just wants a value. */ static std::string @@ -568,7 +769,7 @@ } } } - + /* Concatenate each element in DIRS with NAME (assume each ends with a /, to save time). If SEARCH_ALL is false, return the first readable regular file. Else continue to search for more. In any case, if @@ -607,7 +808,7 @@ if (kpse_readable_file (potential)) { - str_list_add (ret, potential); + ret.append (std::string (potential)); /* Move this element towards the top of the list. */ str_llist_float (dirs, elt); @@ -630,7 +831,7 @@ return ret; } - + /* This is called when NAME is absolute or explicitly relative; if it's readable, return (a list containing) it; otherwise, return NULL. */ @@ -643,11 +844,11 @@ /* Add `found' to the return list even if it's null; that tells the caller we didn't find anything. */ - str_list_add (ret_list, found); + ret_list.append (std::string (found)); return ret_list; } - + /* This is the hard case -- look for NAME in PATH. If ALL is false, return the first file found. Otherwise, search all elements of PATH. */ @@ -718,10 +919,10 @@ if (! found.empty ()) { if (all) - str_list_concat (ret_list, found); + ret_list.append (found); else { - str_list_add (ret_list, found[0]); + ret_list.append (found[0]); done = true; } } @@ -729,7 +930,7 @@ return ret_list; } - + /* Search PATH for ORIGINAL_NAME. If ALL is false, or ORIGINAL_NAME is absolute_p, check ORIGINAL_NAME itself. Otherwise, look at each element of PATH for the first readable ORIGINAL_NAME. @@ -782,7 +983,7 @@ return ret_list; } - + /* Search PATH for the first NAME. */ std::string @@ -794,7 +995,6 @@ return ret_list.empty () ? std::string () : ret_list[0]; } - /* Search all elements of PATH for files named NAME. Not sure if it's right to assert `must_exist' here, but it suffices now. */ @@ -803,7 +1003,7 @@ { return search (path, name, true, true); } - + /* This is the hard case -- look in each element of PATH for each element of NAMES. If ALL is false, return the first file found. Otherwise, search all elements of PATH. */ @@ -901,10 +1101,10 @@ if (! found.empty ()) { if (all) - str_list_concat (ret_list, found); + ret_list.append (found); else { - str_list_add (ret_list, found[0]); + ret_list.append (found[0]); done = true; } } @@ -1106,7 +1306,6 @@ return kpse_tilde_expand (var_expansion); } - /* Forward declarations of functions from the original expand.c */ static char **brace_expand (const char *); static void free_array (char **); @@ -1124,20 +1323,6 @@ if (kpse_dot.empty ()) return path; -#ifdef MSDOS - /* Some setups of ported Bash force $KPSE_DOT to have the //d/foo/bar - form (when `pwd' is used), which is not understood by libc and the OS. - Convert them back to the usual d:/foo/bar form. */ - if (kpse_dot.len > 3 && kpse_dot[0] == '/' && kpse_dot[1] == '/' - && kpse_dot[2] >= 'A' && kpse_dot[2] <= 'z' && kpse_dot[3] == '/') - { - kpse_dot = kpse_dot.substr (1); - kpse_dot = xstrdup (kpse_dot); - kpse_dot[0] = kpse_dot[1]; /* drive letter */ - kpse_dot[1] = ':'; - } -#endif - char *tmp = xstrdup (path.c_str ()); for (elt = kpse_path_element (tmp); elt; elt = kpse_path_element (NULL)) @@ -1231,23 +1416,23 @@ return kpse_expand_kpse_dot (ret); } - + /* Expand all special constructs in a path, and include only the actually existing directories in the result. */ -char * -kpse_path_expand (const char *path) +std::string +kpse_path_expand (const std::string& path_arg) { - char *ret; + std::string ret; char *elt; unsigned len; - /* Initialise ret to the empty string. */ - ret = (char *) xmalloc (1); - *ret = 0; + const char *path = path_arg.c_str (); + len = 0; /* Expand variables and braces first. */ std::string tmp = kpse_brace_expand (path); + const char *xpath = tmp.c_str (); /* Now expand each of the path elements, printing the results */ @@ -1288,22 +1473,21 @@ { const std::string thedir = STR_LLIST (*dir); unsigned dirlen = thedir.length (); - char *save_ret = ret; + /* Retain trailing slash if that's the root directory. */ if (dirlen == 1 || (dirlen == 3 && NAME_BEGINS_WITH_DEVICE (thedir) && IS_DIR_SEP (thedir[2]))) { - ret = concat3 (ret, thedir.c_str (), ENV_SEP_STRING); + ret += thedir + ENV_SEP_STRING; len += dirlen + 1; ret[len - 1] = ENV_SEP; } else { - ret = concat (ret, thedir.c_str ()); + ret += thedir; len += dirlen; ret [len - 1] = ENV_SEP; } - free (save_ret); } } } @@ -1314,7 +1498,7 @@ return ret; } - + /* braces.c -- code for doing word expansion in curly braces. Taken from bash 1.14.5. [Ans subsequently modified for kpatshea.] @@ -1394,7 +1578,6 @@ return (new_array); } - /* Return an array of strings; the brace expansion of TEXT. */ static char ** brace_expand (const char *text) @@ -1453,7 +1636,6 @@ return (result); } - /* Expand the text found inside of braces. We simply try to split the text at BRACE_ARG_SEPARATORs into separate strings. We then brace expand each slot which needs it, until there are no more slots which @@ -1632,7 +1814,6 @@ kpse_src_cmdline /* command-line option */ } kpse_src_type; - /* For each file format, we record the following information. The main thing that is not part of this structure is the environment variable lists. They are used directly in tex-file.c. We could incorporate @@ -1665,7 +1846,7 @@ static kpse_format_info_type kpse_format_info; #define DB_ENVS "TEXMFDBS" - + /* And EXPAND_DEFAULT calls kpse_expand_default on try_path and the present info->path. */ #define EXPAND_DEFAULT(try_path, source_string) \ @@ -1743,7 +1924,6 @@ info->path = tmp; } - /* Some file types have more than one suffix. */ static void @@ -1767,7 +1947,6 @@ (*list)[count] = NULL; } - static char * remove_dbonly (const char *path) { @@ -1877,7 +2056,7 @@ return kpse_format_info.path; } - + static hash_table_type db; /* The hash table for all the ls-R's. */ /* SMALL: The old size of the hash table was 7603, with the assumption that a minimal ls-R bas about 3500 entries. But a typical ls-R will @@ -1898,7 +2077,7 @@ #endif static string_vector db_dir_list; - + /* If DIRNAME contains any element beginning with a `.' (that is more than just `./'), return true. This is to allow ``hidden'' directories -- ones that don't get searched. */ @@ -1917,7 +2096,7 @@ return false; } - + /* Allocate in increments of this size. */ #define BLOCK_SIZE 75 @@ -2052,9 +2231,7 @@ db_file = NULL; } else - { - str_list_add (db_dir_list, top_dir); - } + db_dir_list.append (std::string (top_dir)); #ifdef KPSE_DEBUG if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) @@ -2081,7 +2258,6 @@ return db_file != NULL; } - /* Insert FNAME into the hash table. This is for files that get built during a run. We wouldn't want to reread all of ls-R, even if it got rebuilt. */ @@ -2104,7 +2280,7 @@ hash_insert (&db, file_part, dir_part); } } - + /* Return true if FILENAME could be in PATH_ELT, i.e., if the directory part of FILENAME matches PATH_ELT. Have to consider // wildcards, but $ and ~ expansion have already been done. */ @@ -2216,7 +2392,7 @@ return found; } - + /* If ALIAS_FILENAME exists, read it into TABLE. */ static bool @@ -2279,7 +2455,7 @@ return alias_file != NULL; } - + /* Initialize the path for ls-R files, and read them all into the hash table `db'. If no usable ls-R's are found, set db.buckets to NULL. */ @@ -2336,7 +2512,7 @@ alias_db.buckets = NULL; } } - + /* Avoid doing anything if this PATH_ELT is irrelevant to the databases. */ string_vector @@ -2453,7 +2629,8 @@ /* If we have a real file, add it to the list, maybe done. */ if (! found.empty ()) { - str_list_add (ret, found); + ret.append (found); + if (! (all || found.empty ())) done = true; } @@ -2535,7 +2712,7 @@ /* To avoid giving prototypes for all the routines and then their real definitions, we give all the subroutines first. The entry point is the last routine in the file. */ - + /* Make a copy of DIR (unless it's null) and save it in L. Ensure that DIR ends with a DIR_SEP for the benefit of later searches. */ @@ -2573,7 +2750,7 @@ if (dir_p (dir)) dir_list_add (l, dir); } - + /* The cache. Typically, several paths have the same element; for example, /usr/local/lib/texmf/fonts//. We don't want to compute the expansion of such a thing more than once. Even though we also cache @@ -2604,7 +2781,6 @@ the_cache[cache_length - 1].value = value; } - /* To retrieve, just check the list in order. */ static str_llist_type * @@ -2620,13 +2796,12 @@ return NULL; } - + /* Handle the magic path constructs. */ /* Declare recursively called routine. */ static void expand_elt (str_llist_type *, const char *, unsigned); - /* POST is a pointer into the original element (which may no longer be ELT) to just after the doubled DIR_SEP, perhaps to the null. Append subdirectories of ELT (up to ELT_LENGTH, which must be a /) to @@ -2745,13 +2920,7 @@ some such, we can still find subdirectories, even if it is much slower. */ #ifdef ST_NLINK_TRICK -#ifdef AMIGA - /* With SAS/C++ 6.55 on the Amiga, `stat' sets the `st_nlink' - field to -1 for a file, or to 1 for a directory. */ - if (links == 1) -#else if (links > 2) -#endif /* not AMIGA */ #endif /* not ST_NLINK_TRICK */ /* All criteria are met; find subdirectories. */ do_subdir (str_list_ptr, name.c_str (), @@ -2773,7 +2942,6 @@ #endif /* not WIN32 */ } - /* Assume ELT is non-empty and non-NULL. Return list of corresponding directories (with no terminating NULL entry) in STR_LIST_PTR. Start looking for magic constructs at START. */ @@ -2805,7 +2973,7 @@ /* When we reach the end of ELT, it will be a normal filename. */ checked_dir_list_add (str_list_ptr, elt); } - + /* Here is the entry point. Returns directory list for ELT. */ str_llist_type * @@ -2869,8 +3037,8 @@ disk accesses overwhelm everything else. If ENV_P is true, use IS_ENV_SEP; else use IS_DIR_SEP. */ -static char * -element (const char *passed_path, bool env_p) +char * +kpse_path_element (const char *passed_path) { const char *p; char *ret; @@ -2890,8 +3058,7 @@ /* Find the next colon not enclosed by braces (or the end of the path). */ brace_level = 0; - while (*p != 0 && !(brace_level == 0 - && (env_p ? IS_ENV_SEP (*p) : IS_DIR_SEP (*p)))) + while (*p != 0 && ! (brace_level == 0 && IS_ENV_SEP (*p))) { if (*p == '{') ++brace_level; @@ -2924,46 +3091,6 @@ return ret; } -char * -kpse_path_element (const char *p) -{ - return element (p, true); -} - -char * -kpse_filename_component (const char *p) -{ - return element (p, false); -} - -/* xfopen.c: fopen and fclose with error checking. */ - -/* These routines just check the return status from standard library - routines and abort if an error happens. */ - -FILE * -xfopen (const char *filename, const char *mode) -{ - FILE *f; - - assert (filename && mode); - - f = fopen (filename, mode); - if (f == NULL) - FATAL_PERROR (filename); - - return f; -} - -void -xfclose (FILE *f, const char *filename) -{ - assert (f); - - if (fclose (f) == EOF) - FATAL_PERROR (filename); -} - #ifndef WIN32 void xclosedir (DIR *d) @@ -2979,56 +3106,6 @@ } #endif -/* xmalloc.c: malloc with error checking. */ - -void * -xmalloc (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; -} - -/* xrealloc.c: realloc with error checking. */ - -extern void *xmalloc (unsigned); - -void * -xrealloc (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; -} - -/* xstrdup.c: strdup with error checking. */ - /* dir.c: directory operations. */ #ifndef WIN32 @@ -3066,192 +3143,6 @@ #endif /* !WIN32 */ -/* hash.c: hash table operations. */ - -/* 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 (hash_table_type table, const std::string& key) -{ - unsigned n = 0; - - /* Our keys aren't often anagrams of each other, so no point in - weighting the characters. */ - size_t len = key.length (); - for (size_t i = 0; i < len; i++) - n = (n + n + TRANSFORM (key[i])) % table.size; - - return n; -} - -hash_table_type -hash_create (unsigned size) -{ - /* hash_table_type ret; changed into "static ..." to work around gcc - optimizer bug for Alpha. */ - static hash_table_type ret; - unsigned b; - ret.buckets = new hash_element_type * [size]; - ret.size = size; - - /* calloc's zeroes aren't necessarily NULL, so be safe. */ - 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 (hash_table_type *table, const std::string& key, - const std::string& value) -{ - unsigned n = hash (*table, key); - hash_element_type *new_elt = new 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. */ - -static string_vector -hash_lookup (hash_table_type table, const std::string& key) -{ - hash_element_type *p; - string_vector ret; - unsigned n = hash (table, key); - - /* Look at everything in this bucket. */ - for (p = table.buckets[n]; p != NULL; p = p->next) - if (FILESTRCASEEQ (key.c_str (), p->key.c_str ())) - /* Cast because the general string_vector shouldn't force const data. */ - str_list_add (ret, p->value); - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) - { - DEBUGF1 ("hash_lookup (%s) =>", key.c_str ()); - if (ret.empty ()) - fputs (" (nil)\n", stderr); - else - { - int len = ret.length (); - for (int i = 0; i < len; i++) - { - putc (' ', stderr); - fputs (ret[i].c_str (), stderr); - } - putc ('\n', stderr); - } - fflush (stderr); - } -#endif - - return ret; -} - -/* We only print nonempty buckets, to decrease output volume. */ - -void -hash_print (hash_table_type table, int 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.c_str (), - tb->value.c_str ()); - - 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); -} - -/* concat.c: dynamic string concatenation. */ - -/* Return the concatenation of S1 and S2. See `concatn.c' for a - `concatn', which takes a variable number of arguments. */ - -static char * -concat (const char *s1, const char *s2) -{ - char *answer = (char *) xmalloc (strlen (s1) + strlen (s2) + 1); - strcpy (answer, s1); - strcat (answer, s2); - - return answer; -} - -/* concat3.c: concatenate three strings. */ - -static char * -concat3 (const char *s1, const char *s2, const char *s3) -{ - char *answer - = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); - strcpy (answer, s1); - strcat (answer, s2); - strcat (answer, s3); - - return answer; -} - /* debug.c: Help the user discover what's going on. */ #ifdef KPSE_DEBUG @@ -3287,34 +3178,6 @@ #endif -/* str-list.c: define routines for string lists. */ - -/* See the lib.h file for comments. */ - -static void -str_list_add (string_vector& l, const std::string& s) -{ - int len = l.length (); - l.resize (len + 1); - l[len] = s; -} - -/* May as well save some reallocations and do everything in a chunk - instead of calling str_list_add on each element. */ - -void -str_list_concat (string_vector& target, const string_vector& more) -{ - int e; - int prev_len = target.length (); - int new_len = prev_len + more.length (); - - target.resize (new_len); - - for (e = 0; e < more.length (); e++) - target[prev_len + e] = more[e]; -} - /* str-llist.c: Implementation of a linked list of strings. */ /* Add the new string STR to the end of the list L. */ @@ -3339,7 +3202,7 @@ else STR_LLIST_NEXT (*e) = new_elt; } - + /* Move an element towards the top. The idea is that when a file is found in a given directory, later files will likely be in that same directory, and looking for the file in all the directories in between @@ -3391,7 +3254,6 @@ /* variable.c: variable expansion. */ - /* We have to keep track of variables being expanded, otherwise constructs like TEXINPUTS = $TEXINPUTS result in an infinite loop. (Or indirectly recursive variables, etc.) Our simple solution is to @@ -3414,7 +3276,7 @@ return (expansions.find (var) != expansions.end ()) ? expansions[var] : false; } - + /* Append the result of value of `var' to EXPANSION, where `var' begins at START and ends at END. If `var' is not set, do not complain. This is a subroutine for the more complicated expansion function. */ @@ -3441,7 +3303,7 @@ } } } - + /* Can't think of when it would be useful to change these (and the diagnostic messages assume them), but ... */ #ifndef IS_VAR_START /* starts all variable references */ @@ -3457,7 +3319,6 @@ #define IS_VAR_END_DELIMITER(c) ((c) == '}') #endif - /* Maybe we should support some or all of the various shell ${...} constructs, especially ${var-value}. */
--- a/liboctave/kpse.h +++ b/liboctave/kpse.h @@ -120,7 +120,7 @@ result, then expand any `//' constructs. The final expansion (always in fresh memory) is a path of all the existing directories that match the pattern. */ -extern char *kpse_path_expand (const char *path); +extern std::string kpse_path_expand (const std::string& path); /* default.h: Declare default path expander. */
--- a/liboctave/pathsearch.cc +++ b/liboctave/pathsearch.cc @@ -129,29 +129,19 @@ octave_kpathsea_initialized = true; } - char *t1 = 0; - if (p_default.empty ()) - t1 = kpse_path_expand (p_orig.c_str ()); + p = kpse_path_expand (p_orig); else { char *t2 = kpse_expand_default (p_orig.c_str (), p_default.c_str ()); - t1 = kpse_path_expand (t2); + p = kpse_path_expand (t2); if (t2) free (t2); } - if (t1) - { - p = t1; - free (t1); - } - else - p = std::string (); - int count = 0; char *path_elt = kpse_path_element (p.c_str ()); while (path_elt)
--- a/liboctave/str-vec.cc +++ b/liboctave/str-vec.cc @@ -97,6 +97,33 @@ return *this; } +string_vector& +string_vector::append (const std::string& s) +{ + int len = length (); + + resize (len + 1); + + elem(len) = s; + + return *this; +} + +string_vector& +string_vector::append (const string_vector& sv) +{ + int len = length (); + + int new_len = len + sv.length (); + + resize (new_len); + + for (int i = 0; i < new_len; i++) + elem(len + i) = sv[i]; + + return *this; +} + char ** string_vector::c_str_vec (void) const {